ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/channel.c
Revision: 9456
Committed: Tue Jun 30 17:33:43 2020 UTC (3 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 33616 byte(s)
Log Message:
- Rename find_channel_link() to member_find_link()

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 9102 * Copyright (c) 1997-2020 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4564 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22     /*! \file channel.c
23     * \brief Responsible for managing channels, members, bans and topics
24 knight 31 * \version $Id$
25 adx 30 */
26    
27     #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #include "channel.h"
30 michael 9266 #include "channel_invite.h"
31 adx 30 #include "channel_mode.h"
32     #include "client.h"
33     #include "hash.h"
34 michael 1632 #include "conf.h"
35 michael 7235 #include "conf_resv.h"
36 michael 371 #include "hostmask.h"
37 adx 30 #include "irc_string.h"
38     #include "ircd.h"
39     #include "numeric.h"
40 michael 3347 #include "server.h"
41 adx 30 #include "send.h"
42     #include "event.h"
43     #include "memory.h"
44 michael 3347 #include "misc.h"
45 michael 9233 #include "extban.h"
46 adx 30
47 michael 3235
48 michael 8438 /** Doubly linked list containing a list of all channels. */
49     static dlink_list channel_list;
50 adx 30
51    
52 michael 8438 /*! \brief Returns the channel_list as constant
53     * \return channel_list
54     */
55     const dlink_list *
56     channel_get_list(void)
57     {
58     return &channel_list;
59     }
60    
61 michael 3308 /*! \brief Adds a user to a channel by adding another link to the
62 adx 30 * channels member chain.
63 michael 9082 * \param channel Pointer to channel to add client to
64 michael 9249 * \param client Pointer to client (who) to add
65 michael 3308 * \param flags Flags for chanops etc
66     * \param flood_ctrl Whether to count this join in flood calculations
67 adx 30 */
68     void
69 michael 9249 add_user_to_channel(struct Channel *channel, struct Client *client,
70 michael 8663 unsigned int flags, bool flood_ctrl)
71 adx 30 {
72 michael 9249 assert(IsClient(client));
73 michael 5591
74 michael 7778 if (GlobalSetOptions.joinfloodtime)
75 adx 30 {
76 michael 8663 if (flood_ctrl == true)
77 michael 9082 ++channel->number_joined;
78 adx 30
79 michael 9082 channel->number_joined -= (event_base->time.sec_monotonic - channel->last_join_time) *
80 adx 30 (((float)GlobalSetOptions.joinfloodcount) /
81     (float)GlobalSetOptions.joinfloodtime);
82    
83 michael 9082 if (channel->number_joined <= 0)
84 adx 30 {
85 michael 9082 channel->number_joined = 0;
86     ClearJoinFloodNoticed(channel);
87 adx 30 }
88 michael 9082 else if (channel->number_joined >= GlobalSetOptions.joinfloodcount)
89 adx 30 {
90 michael 9082 channel->number_joined = GlobalSetOptions.joinfloodcount;
91 adx 30
92 michael 9082 if (!IsSetJoinFloodNoticed(channel))
93 adx 30 {
94 michael 9082 SetJoinFloodNoticed(channel);
95 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
96 adx 30 "Possible Join Flooder %s on %s target: %s",
97 michael 9249 client_get_name(client, HIDE_IP),
98     client->servptr->name, channel->name);
99 adx 30 }
100     }
101    
102 michael 9082 channel->last_join_time = event_base->time.sec_monotonic;
103 adx 30 }
104    
105 michael 9082 struct ChannelMember *member = xcalloc(sizeof(*member));
106 michael 9249 member->client = client;
107 michael 9082 member->channel = channel;
108 michael 4816 member->flags = flags;
109 adx 30
110 michael 9082 dlinkAdd(member, &member->channode, &channel->members);
111 michael 4171
112 michael 9249 if (MyConnect(client))
113 michael 9082 dlinkAdd(member, &member->locchannode, &channel->members_local);
114 michael 4171
115 michael 9249 dlinkAdd(member, &member->usernode, &client->channel);
116 adx 30 }
117    
118 michael 3308 /*! \brief Deletes an user from a channel by removing a link in the
119 adx 30 * channels member chain.
120 michael 3308 * \param member Pointer to Membership struct
121 adx 30 */
122     void
123 michael 9082 remove_user_from_channel(struct ChannelMember *member)
124 adx 30 {
125 michael 9249 struct Client *const client = member->client;
126 michael 9082 struct Channel *const channel = member->channel;
127 adx 30
128 michael 9082 dlinkDelete(&member->channode, &channel->members);
129 michael 4171
130 michael 9249 if (MyConnect(client))
131 michael 9082 dlinkDelete(&member->locchannode, &channel->members_local);
132 michael 4171
133 michael 9249 dlinkDelete(&member->usernode, &client->channel);
134 adx 30
135 michael 8384 xfree(member);
136 adx 30
137 michael 9082 if (channel->members.head == NULL)
138     channel_free(channel);
139 adx 30 }
140    
141 michael 9449 /* remove_a_mode()
142     *
143     * inputs -
144     * output - NONE
145     * side effects - remove ONE mode from a channel
146     */
147     void
148     channel_demote_members(struct Channel *channel, const struct Client *client, unsigned int mask, const char flag)
149     {
150     dlink_node *node;
151     char modebuf[MODEBUFLEN];
152     char parabuf[MODEBUFLEN];
153     char *mbuf = modebuf;
154     char *pbuf = modebuf;
155     const char *names[MAXMODEPARAMS];
156     static const unsigned int names_size = sizeof(names) / sizeof(names[0]);
157     unsigned int count = 0;
158    
159     DLINK_FOREACH(node, channel->members.head)
160     {
161     struct ChannelMember *member = node->data;
162    
163     if ((member->flags & mask) == 0)
164     continue;
165    
166     member->flags &= ~mask;
167    
168     names[count++] = member->client->name;
169    
170     *mbuf++ = flag;
171    
172     if (count >= names_size)
173     {
174     *mbuf = '\0';
175    
176     for (unsigned int i = 0; i < names_size; ++i)
177     pbuf += snprintf(pbuf, sizeof(parabuf) - (pbuf - parabuf), " %s", names[i]);
178    
179     sendto_channel_local(NULL, channel, 0, 0, 0, ":%s MODE %s -%s%s",
180     client->name, channel->name, modebuf, parabuf);
181     mbuf = modebuf;
182     pbuf = parabuf;
183     count = 0;
184     }
185     }
186    
187     if (count)
188     {
189     assert(count < names_size);
190     *mbuf = '\0';
191    
192     for (unsigned int i = 0; i < count; ++i)
193     pbuf += snprintf(pbuf, sizeof(parabuf) - (pbuf - parabuf), " %s", names[i]);
194    
195     sendto_channel_local(NULL, channel, 0, 0, 0, ":%s MODE %s -%s%s",
196     client->name, channel->name, modebuf, parabuf);
197     }
198     }
199    
200 michael 6374 /* channel_send_members()
201 adx 30 *
202     * inputs -
203     * output - NONE
204     * side effects -
205     */
206     static void
207 michael 9249 channel_send_members(struct Client *client, const struct Channel *channel,
208 michael 7796 const char *modebuf, const char *parabuf)
209 adx 30 {
210 michael 8058 dlink_node *node;
211 michael 9085 char buf[IRCD_BUFSIZE];
212 adx 30 int tlen; /* length of text to append */
213     char *t, *start; /* temp char pointer */
214    
215 michael 6781 start = t = buf + snprintf(buf, sizeof(buf), ":%s SJOIN %ju %s %s %s:",
216 michael 9082 me.id, channel->creation_time,
217     channel->name, modebuf, parabuf);
218 adx 30
219 michael 9082 DLINK_FOREACH(node, channel->members.head)
220 adx 30 {
221 michael 9082 const struct ChannelMember *member = node->data;
222 adx 30
223 michael 9082 tlen = strlen(member->client->id) + 1; /* +1 for space */
224 michael 9453 tlen += member_get_prefix_len(member, true);
225 adx 30
226 michael 3250 /*
227     * Space will be converted into CR, but we also need space for LF..
228 michael 3783 * That's why we use '- 1' here -adx
229 michael 3250 */
230 michael 1330 if (t + tlen - buf > IRCD_BUFSIZE - 1)
231 adx 30 {
232 michael 3250 *(t - 1) = '\0'; /* Kill the space and terminate the string */
233 michael 9249 sendto_one(client, "%s", buf);
234 adx 30 t = start;
235     }
236    
237 michael 9453 t += snprintf(t, sizeof(buf) - (t - buf), "%s%s ", member_get_prefix(member, true), member->client->id);
238 adx 30 }
239    
240 michael 3250 /* Should always be non-NULL unless we have a kind of persistent channels */
241 michael 9082 if (channel->members.head)
242 michael 8430 --t; /* Take the space out */
243 adx 30 *t = '\0';
244 michael 9249 sendto_one(client, "%s", buf);
245 adx 30 }
246    
247 michael 3308 /*! \brief Sends +b/+e/+I
248 michael 9249 * \param client Client pointer to server
249 michael 9082 * \param channel Pointer to channel
250 michael 3998 * \param list Pointer to list of modes to send
251 michael 3308 * \param flag Char flag flagging type of mode. Currently this can be 'b', e' or 'I'
252 adx 30 */
253     static void
254 michael 9249 channel_send_mask_list(struct Client *client, const struct Channel *channel,
255 michael 6374 const dlink_list *list, const char flag)
256 adx 30 {
257 michael 7686 dlink_node *node;
258 michael 9085 char mbuf[IRCD_BUFSIZE];
259     char pbuf[IRCD_BUFSIZE];
260 michael 9347 size_t tlen, mlen, cur_len;
261 michael 3144 char *pp = pbuf;
262 adx 30
263 michael 8446 if (dlink_list_length(list) == 0)
264 adx 30 return;
265    
266 michael 6781 mlen = snprintf(mbuf, sizeof(mbuf), ":%s BMASK %ju %s %c :", me.id,
267 michael 9082 channel->creation_time, channel->name, flag);
268 michael 3135 cur_len = mlen;
269 adx 30
270 michael 4801 DLINK_FOREACH(node, list->head)
271 adx 30 {
272 michael 4816 const struct Ban *ban = node->data;
273 adx 30
274 michael 9233 tlen = ban->banstr_len + 1; /* +1 for space */
275 adx 30
276     /*
277 michael 3995 * Send buffer and start over if we cannot fit another ban
278 adx 30 */
279 michael 9347 if (cur_len + (tlen - 1) > sizeof(pbuf) - 2)
280 adx 30 {
281 michael 3250 *(pp - 1) = '\0'; /* Get rid of trailing space on buffer */
282 michael 9249 sendto_one(client, "%s%s", mbuf, pbuf);
283 adx 30
284 michael 3135 cur_len = mlen;
285 adx 30 pp = pbuf;
286     }
287    
288 michael 9347 pp += snprintf(pp, sizeof(pbuf) - (pp - pbuf), "%s ", ban->banstr);
289 adx 30 cur_len += tlen;
290     }
291    
292 michael 3250 *(pp - 1) = '\0'; /* Get rid of trailing space on buffer */
293 michael 9249 sendto_one(client, "%s%s", mbuf, pbuf);
294 adx 30 }
295    
296 michael 9249 /*! \brief Send "client" a full list of the modes for channel channel
297     * \param client Pointer to client client
298     * \param channel Pointer to channel pointer
299 adx 30 */
300     void
301 michael 9249 channel_send_modes(struct Client *client, const struct Channel *channel)
302 adx 30 {
303 michael 3145 char modebuf[MODEBUFLEN] = "";
304     char parabuf[MODEBUFLEN] = "";
305    
306 michael 9249 channel_modes(channel, client, modebuf, parabuf);
307     channel_send_members(client, channel, modebuf, parabuf);
308 adx 30
309 michael 9249 channel_send_mask_list(client, channel, &channel->banlist, 'b');
310     channel_send_mask_list(client, channel, &channel->exceptlist, 'e');
311     channel_send_mask_list(client, channel, &channel->invexlist, 'I');
312 adx 30 }
313    
314 michael 3308 /*! \brief Check channel name for invalid characters
315     * \param name Pointer to channel name string
316     * \param local Indicates whether it's a local or remote creation
317 michael 632 * \return 0 if invalid, 1 otherwise
318 adx 30 */
319 michael 8659 bool
320     channel_check_name(const char *name, bool local)
321 adx 30 {
322 michael 632 const char *p = name;
323 michael 3422
324 michael 5591 assert(!EmptyString(p));
325 adx 30
326 michael 632 if (!IsChanPrefix(*p))
327 michael 8659 return false;
328 adx 30
329 michael 8659 if (local == false || ConfigChannel.disable_fake_channels == 0)
330 michael 632 {
331     while (*++p)
332 db 634 if (!IsChanChar(*p))
333 michael 8659 return false;
334 michael 632 }
335     else
336     {
337     while (*++p)
338 db 634 if (!IsVisibleChanChar(*p))
339 michael 8659 return false;
340 michael 632 }
341    
342 michael 3422 return p - name <= CHANNELLEN;
343 adx 30 }
344    
345     void
346 michael 4816 remove_ban(struct Ban *ban, dlink_list *list)
347 adx 30 {
348 michael 4816 dlinkDelete(&ban->node, list);
349 michael 8384 xfree(ban);
350 adx 30 }
351    
352 michael 6374 /* channel_free_mask_list()
353 adx 30 *
354     * inputs - pointer to dlink_list
355     * output - NONE
356     * side effects -
357     */
358 michael 6374 static void
359     channel_free_mask_list(dlink_list *list)
360 adx 30 {
361 michael 7265 while (list->head)
362     {
363     struct Ban *ban = list->head->data;
364     remove_ban(ban, list);
365     }
366 adx 30 }
367    
368 michael 4617 /*! \brief Get Channel block for name (and allocate a new channel
369 adx 30 * block, if it didn't exist before)
370 michael 4617 * \param name Channel name
371 michael 3308 * \return Channel block
372 adx 30 */
373     struct Channel *
374 michael 6374 channel_make(const char *name)
375 adx 30 {
376 michael 4617 assert(!EmptyString(name));
377 adx 30
378 michael 9082 struct Channel *channel = xcalloc(sizeof(*channel));
379     channel->hnextch = channel;
380 michael 3308 /* Doesn't hurt to set it here */
381 michael 9082 channel->creation_time = event_base->time.sec_real;
382     channel->last_join_time = event_base->time.sec_monotonic;
383 adx 30
384 michael 8028 /* Cache channel name length to avoid repetitive strlen() calls. */
385 michael 9082 channel->name_len = strlcpy(channel->name, name, sizeof(channel->name));
386     if (channel->name_len >= sizeof(channel->name))
387     channel->name_len = sizeof(channel->name) - 1;
388 michael 6989
389 michael 9082 dlinkAdd(channel, &channel->node, &channel_list);
390     hash_add_channel(channel);
391 adx 30
392 michael 9082 return channel;
393 adx 30 }
394    
395 michael 3308 /*! \brief Walk through this channel, and destroy it.
396 michael 9082 * \param channel Channel pointer
397 adx 30 */
398     void
399 michael 9082 channel_free(struct Channel *channel)
400 adx 30 {
401 michael 9266 invite_clear_list(&channel->invites);
402 adx 30
403 michael 3308 /* Free ban/exception/invex lists */
404 michael 9082 channel_free_mask_list(&channel->banlist);
405     channel_free_mask_list(&channel->exceptlist);
406     channel_free_mask_list(&channel->invexlist);
407 adx 30
408 michael 9082 dlinkDelete(&channel->node, &channel_list);
409     hash_del_channel(channel);
410 adx 30
411 michael 9082 assert(channel->hnextch == channel);
412 michael 8589
413 michael 9082 assert(channel->node.prev == NULL);
414     assert(channel->node.next == NULL);
415 michael 8589
416 michael 9082 assert(dlink_list_length(&channel->members_local) == 0);
417     assert(channel->members_local.head == NULL);
418     assert(channel->members_local.tail == NULL);
419 michael 8589
420 michael 9082 assert(dlink_list_length(&channel->members) == 0);
421     assert(channel->members.head == NULL);
422     assert(channel->members.tail == NULL);
423 michael 8589
424 michael 9082 assert(dlink_list_length(&channel->invites) == 0);
425     assert(channel->invites.head == NULL);
426     assert(channel->invites.tail == NULL);
427 michael 8589
428 michael 9082 assert(dlink_list_length(&channel->banlist) == 0);
429     assert(channel->banlist.head == NULL);
430     assert(channel->banlist.tail == NULL);
431 michael 8589
432 michael 9082 assert(dlink_list_length(&channel->exceptlist) == 0);
433     assert(channel->exceptlist.head == NULL);
434     assert(channel->exceptlist.tail == NULL);
435 michael 8589
436 michael 9082 assert(dlink_list_length(&channel->invexlist) == 0);
437     assert(channel->invexlist.head == NULL);
438     assert(channel->invexlist.tail == NULL);
439 michael 8589
440 michael 9082 xfree(channel);
441 adx 30 }
442    
443     /*!
444 michael 9082 * \param channel Pointer to channel
445 michael 3308 * \return String pointer "=" if public, "@" if secret else "*"
446 adx 30 */
447     static const char *
448 michael 9082 channel_pub_or_secret(const struct Channel *channel)
449 adx 30 {
450 michael 9082 if (SecretChannel(channel))
451 adx 30 return "@";
452 michael 9082 if (PrivateChannel(channel))
453 adx 30 return "*";
454     return "=";
455     }
456    
457     /*! \brief lists all names on given channel
458 michael 9249 * \param client Pointer to client struct requesting names
459 michael 9082 * \param channel Pointer to channel block
460 michael 3308 * \param show_eon Show RPL_ENDOFNAMES numeric or not
461 adx 30 * (don't want it with /names with no params)
462     */
463     void
464 michael 9249 channel_member_names(struct Client *client, struct Channel *channel, bool show_eon)
465 adx 30 {
466 michael 7686 dlink_node *node;
467 michael 9085 char buf[IRCD_BUFSIZE + 1];
468 michael 9416 char *bufptr = buf;
469     size_t masklen = 0;
470 michael 9456 bool is_member = member_find_link(client, channel) != NULL;
471 michael 9249 bool multi_prefix = HasCap(client, CAP_MULTI_PREFIX) != 0;
472     bool uhnames = HasCap(client, CAP_UHNAMES) != 0;
473 adx 30
474 michael 9249 assert(IsClient(client));
475 michael 5591
476 michael 9082 if (PubChannel(channel) || is_member == true)
477 adx 30 {
478 michael 9416 /* :me.name 353 source_p->name @ channel->name :+nick1 @nick2 %nick3 ...\r\n */
479     /* 1 23456 789 01 2 3 */
480     size_t len = strlen(me.name) + strlen(client->name) + channel->name_len + 13;
481 adx 30
482 michael 9082 DLINK_FOREACH(node, channel->members.head)
483 adx 30 {
484 michael 9082 const struct ChannelMember *member = node->data;
485 adx 30
486 michael 9082 if (HasUMode(member->client, UMODE_INVISIBLE) && is_member == false)
487 adx 30 continue;
488    
489 michael 8655 if (uhnames == true)
490 michael 9416 masklen = strlen(member->client->name) + strlen(member->client->username) +
491     strlen(member->client->host) + 3; /* +3 for ! + @ + space */
492 michael 8430 else
493 michael 9416 masklen = strlen(member->client->name) + 1; /* +1 for space */
494 adx 30
495 michael 9453 masklen += member_get_prefix_len(member, multi_prefix);
496 michael 506
497 michael 9416 if ((bufptr - buf) + masklen + len > sizeof(buf))
498 adx 30 {
499 michael 9416 *(bufptr - 1) = '\0';
500     sendto_one_numeric(client, &me, RPL_NAMREPLY,
501     channel_pub_or_secret(channel), channel->name, buf);
502     bufptr = buf;
503 adx 30 }
504    
505 michael 8655 if (uhnames == true)
506 michael 9416 bufptr += snprintf(bufptr, sizeof(buf) - (bufptr - buf), "%s%s!%s@%s ",
507 michael 9453 member_get_prefix(member, multi_prefix),
508 michael 9416 member->client->name, member->client->username,
509     member->client->host);
510 michael 8430 else
511 michael 9416 bufptr += snprintf(bufptr, sizeof(buf) - (bufptr - buf), "%s%s ",
512 michael 9453 member_get_prefix(member, multi_prefix),
513 michael 9416 member->client->name);
514 adx 30 }
515    
516 michael 9416 if (bufptr != buf)
517 adx 30 {
518 michael 9416 *(bufptr - 1) = '\0';
519     sendto_one_numeric(client, &me, RPL_NAMREPLY,
520     channel_pub_or_secret(channel), channel->name, buf);
521 adx 30 }
522     }
523    
524 michael 8655 if (show_eon == true)
525 michael 9249 sendto_one_numeric(client, &me, RPL_ENDOFNAMES, channel->name);
526 adx 30 }
527    
528 michael 9453 /* member_get_prefix()
529 adx 30 *
530 michael 9082 * inputs - pointer to struct ChannelMember
531 adx 30 * - YES if we can combine different flags
532     * output - string either @, +, % or "" depending on whether
533     * chanop, voiced or user
534     * side effects -
535     *
536     * NOTE: Returned string is usually a static buffer
537 michael 7996 * (like in client_get_name)
538 adx 30 */
539     const char *
540 michael 9453 member_get_prefix(const struct ChannelMember *member, bool combine)
541 adx 30 {
542 michael 6902 static char buffer[CMEMBER_STATUS_FLAGS_LEN + 1]; /* +1 for \0 */
543 michael 1902 char *p = buffer;
544 adx 30
545 michael 4816 if (member->flags & CHFL_CHANOP)
546 adx 30 {
547 michael 8655 if (combine == false)
548 adx 30 return "@";
549     *p++ = '@';
550     }
551    
552 michael 4816 if (member->flags & CHFL_HALFOP)
553 adx 30 {
554 michael 8655 if (combine == false)
555 adx 30 return "%";
556     *p++ = '%';
557     }
558    
559 michael 4816 if (member->flags & CHFL_VOICE)
560 adx 30 *p++ = '+';
561     *p = '\0';
562    
563     return buffer;
564     }
565    
566 michael 9453 size_t
567     member_get_prefix_len(const struct ChannelMember *member, bool combine)
568     {
569     size_t len = 0;
570    
571     if (member->flags & CHFL_CHANOP)
572     {
573     if (combine == false)
574     return 1;
575     ++len;
576     }
577    
578     if (member->flags & CHFL_HALFOP)
579     {
580     if (combine == false)
581     return 1;
582     ++len;
583     }
584    
585     if (member->flags & CHFL_VOICE)
586     {
587     if (combine == false)
588     return 1;
589     ++len;
590     }
591    
592     return len;
593     }
594    
595 adx 30 /*!
596 michael 9249 * \param client Pointer to Client to check
597     * \param list Pointer to ban list to search
598 adx 30 * \return 1 if ban found for given n!u\@h mask, 0 otherwise
599     */
600 michael 8663 static bool
601 michael 9249 ban_matches(struct Client *client, struct Channel *channel, struct Ban *ban)
602 adx 30 {
603 michael 9233 /* Is a matching extban, call custom match handler */
604     if (ban->extban & extban_matching_mask())
605     {
606     struct Extban *extban = extban_find_flag(ban->extban & extban_matching_mask());
607     if (extban == NULL)
608     return false;
609    
610 michael 9249 if (extban->matches == NULL || extban->matches(client, channel, ban) == EXTBAN_NO_MATCH)
611 michael 9233 return false;
612    
613     return true;
614     }
615    
616 michael 9249 if (match(ban->name, client->name) == 0 && match(ban->user, client->username) == 0)
617 michael 9233 {
618     switch (ban->type)
619     {
620     case HM_HOST:
621 michael 9249 if (match(ban->host, client->realhost) == 0 ||
622     match(ban->host, client->sockhost) == 0 || match(ban->host, client->host) == 0)
623 michael 9233 return true;
624     break;
625     case HM_IPV4:
626 michael 9249 if (client->ip.ss.ss_family == AF_INET)
627     if (match_ipv4(&client->ip, &ban->addr, ban->bits))
628 michael 9233 return true;
629     break;
630     case HM_IPV6:
631 michael 9249 if (client->ip.ss.ss_family == AF_INET6)
632     if (match_ipv6(&client->ip, &ban->addr, ban->bits))
633 michael 9233 return true;
634     break;
635     default:
636     assert(0);
637     }
638     }
639    
640     return false;
641     }
642    
643     bool
644 michael 9249 find_bmask(struct Client *client, struct Channel *channel, const dlink_list *list, struct Extban *extban)
645 michael 9233 {
646 michael 7686 dlink_node *node;
647 adx 30
648 michael 4801 DLINK_FOREACH(node, list->head)
649 adx 30 {
650 michael 9233 struct Ban *ban = node->data;
651 adx 30
652 michael 9233 /* Looking for a specific type of extban? */
653     if (extban)
654 michael 371 {
655 michael 9233 if (!(ban->extban & extban->flag))
656     continue;
657 michael 371 }
658 michael 9233 else
659     {
660     /*
661     * Acting extbans have their own time they act and are not general purpose bans,
662     * so skip them unless we are hunting them.
663     */
664     if (ban->extban & extban_acting_mask())
665     continue;
666     }
667    
668 michael 9249 bool matches = ban_matches(client, channel, ban);
669 michael 9233 if (matches == false)
670     continue;
671    
672     return true;
673 adx 30 }
674    
675 michael 8663 return false;
676 adx 30 }
677    
678     /*!
679 michael 9249 * \param channel Pointer to channel block
680     * \param client Pointer to client to check access fo
681 adx 30 * \return 0 if not banned, 1 otherwise
682     */
683 michael 8663 bool
684 michael 9249 is_banned(struct Channel *channel, struct Client *client)
685 adx 30 {
686 michael 9249 if (find_bmask(client, channel, &channel->banlist, NULL) == true)
687     return find_bmask(client, channel, &channel->exceptlist, NULL) == false;
688 michael 8663 return false;
689 adx 30 }
690    
691 michael 3308 /*! Tests if a client can join a certain channel
692 michael 9249 * \param client Pointer to client attempting to join
693 michael 9082 * \param channel Pointer to channel
694 michael 3308 * \param key Key sent by client attempting to join if present
695 adx 30 * \return ERR_BANNEDFROMCHAN, ERR_INVITEONLYCHAN, ERR_CHANNELISFULL
696     * or 0 if allowed to join.
697     */
698 michael 6882 static int
699 michael 9249 can_join(struct Client *client, struct Channel *channel, const char *key)
700 adx 30 {
701 michael 9249 if (HasCMode(channel, MODE_SECUREONLY) && !HasUMode(client, UMODE_SECURE))
702 michael 9156 return ERR_SECUREONLYCHAN;
703 michael 1150
704 michael 9249 if (HasCMode(channel, MODE_REGONLY) && !HasUMode(client, UMODE_REGISTERED))
705 michael 1173 return ERR_NEEDREGGEDNICK;
706    
707 michael 9249 if (HasCMode(channel, MODE_OPERONLY) && !HasUMode(client, UMODE_OPER))
708 michael 1150 return ERR_OPERONLYCHAN;
709    
710 michael 9082 if (HasCMode(channel, MODE_INVITEONLY))
711 michael 9266 if (invite_find(channel, client) == NULL)
712 michael 9249 if (find_bmask(client, channel, &channel->invexlist, NULL) == false)
713 adx 30 return ERR_INVITEONLYCHAN;
714    
715 michael 9082 if (channel->mode.key[0] && (key == NULL || strcmp(channel->mode.key, key)))
716 adx 30 return ERR_BADCHANNELKEY;
717    
718 michael 9082 if (channel->mode.limit && dlink_list_length(&channel->members) >=
719     channel->mode.limit)
720 adx 30 return ERR_CHANNELISFULL;
721    
722 michael 9249 if (is_banned(channel, client) == true)
723 michael 2208 return ERR_BANNEDFROMCHAN;
724    
725 michael 9249 return extban_join_can_join(channel, client, NULL);
726 adx 30 }
727    
728     int
729 michael 9082 has_member_flags(const struct ChannelMember *member, const unsigned int flags)
730 adx 30 {
731 michael 4816 return member && (member->flags & flags);
732 adx 30 }
733    
734 michael 9082 struct ChannelMember *
735 michael 9456 member_find_link(const struct Client *client, const struct Channel *channel)
736 adx 30 {
737 michael 7913 dlink_node *node;
738 adx 30
739 michael 9249 if (!IsClient(client))
740 adx 30 return NULL;
741    
742 michael 8438 /* Take the shortest of the two lists */
743 michael 9249 if (dlink_list_length(&channel->members) < dlink_list_length(&client->channel))
744 michael 2567 {
745 michael 9082 DLINK_FOREACH(node, channel->members.head)
746 michael 9249 if (((struct ChannelMember *)node->data)->client == client)
747 michael 4801 return node->data;
748 michael 2567 }
749     else
750     {
751 michael 9249 DLINK_FOREACH(node, client->channel.head)
752 michael 9082 if (((struct ChannelMember *)node->data)->channel == channel)
753 michael 4801 return node->data;
754 michael 2567 }
755 adx 30
756     return NULL;
757     }
758    
759 michael 4782 /*! Checks if a message contains control codes
760 michael 3889 * \param message The actual message string the client wants to send
761     * \return 1 if the message does contain any control codes, 0 otherwise
762 michael 1937 */
763 michael 8657 static bool
764 michael 1937 msg_has_ctrls(const char *message)
765     {
766 michael 9355 const unsigned char *p = (const unsigned char *)message;
767    
768     for (; *p; ++p)
769 michael 1937 {
770     if (*p > 31 || *p == 1)
771 michael 3953 continue; /* No control code or CTCP */
772 michael 1937
773 michael 3889 if (*p == 27) /* Escape */
774 michael 1937 {
775 michael 3889 /* ISO 2022 charset shift sequence */
776 michael 1937 if (*(p + 1) == '$' ||
777     *(p + 1) == '(')
778     {
779     ++p;
780     continue;
781     }
782     }
783    
784 michael 8657 return true; /* Control code */
785 michael 1937 }
786    
787 michael 8657 return false; /* No control code found */
788 michael 1937 }
789    
790 michael 3308 /*! Tests if a client can send to a channel
791 michael 9249 * \param channel Pointer to Channel struct
792     * \param client Pointer to Client struct
793     * \param member Pointer to Membership struct (can be NULL)
794     * \param message The actual message string the client wants to send
795 adx 30 * \return CAN_SEND_OPV if op or voiced on channel\n
796     * CAN_SEND_NONOP if can send to channel but is not an op\n
797 michael 1173 * ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
798 adx 30 */
799     int
800 michael 9249 can_send(struct Channel *channel, struct Client *client,
801 michael 9082 struct ChannelMember *member, const char *message, bool notice)
802 adx 30 {
803 michael 9085 const struct ResvItem *resv;
804 michael 1858
805 michael 9249 if (IsServer(client) || HasFlag(client, FLAGS_SERVICE))
806 adx 30 return CAN_SEND_OPV;
807    
808 michael 9249 if (MyConnect(client) && !HasFlag(client, FLAGS_EXEMPTRESV))
809     if (!(HasUMode(client, UMODE_OPER) && HasOFlag(client, OPER_FLAG_JOIN_RESV)))
810     if ((resv = resv_find(channel->name, match)) && resv_exempt_find(client, resv) == false)
811 michael 1834 return ERR_CANNOTSENDTOCHAN;
812 adx 30
813 michael 9082 if (HasCMode(channel, MODE_NOCTRL) && msg_has_ctrls(message) == true)
814 michael 1944 return ERR_NOCTRLSONCHAN;
815 michael 4883
816 michael 9082 if (HasCMode(channel, MODE_NOCTCP))
817 michael 5466 if (*message == '\001' && strncmp(message + 1, "ACTION ", 7))
818 michael 5463 return ERR_NOCTCP;
819    
820 michael 9456 if (member || (member = member_find_link(client, channel)))
821 michael 5582 if (member->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
822 adx 30 return CAN_SEND_OPV;
823 michael 4883
824 michael 9082 if (member == NULL && HasCMode(channel, MODE_NOPRIVMSGS))
825 michael 2441 return ERR_CANNOTSENDTOCHAN;
826 michael 4883
827 michael 9082 if (HasCMode(channel, MODE_MODERATED))
828 michael 1944 return ERR_CANNOTSENDTOCHAN;
829 michael 4883
830 michael 9249 if (HasCMode(channel, MODE_MODREG) && !HasUMode(client, UMODE_REGISTERED))
831 michael 1944 return ERR_NEEDREGGEDNICK;
832 adx 30
833 michael 9082 if (HasCMode(channel, MODE_NONOTICE) && notice == true)
834 michael 6918 return ERR_CANNOTSENDTOCHAN;
835    
836 michael 3308 /* Cache can send if banned */
837 michael 9249 if (MyConnect(client))
838 michael 1944 {
839 michael 4816 if (member)
840 adx 30 {
841 michael 4816 if (member->flags & CHFL_BAN_SILENCED)
842 michael 1834 return ERR_CANNOTSENDTOCHAN;
843 adx 30
844 michael 4816 if (!(member->flags & CHFL_BAN_CHECKED))
845 adx 30 {
846 michael 9249 if (is_banned(channel, client) == true)
847 adx 30 {
848 michael 5582 member->flags |= (CHFL_BAN_CHECKED | CHFL_BAN_SILENCED);
849 michael 1834 return ERR_CANNOTSENDTOCHAN;
850 adx 30 }
851    
852 michael 4816 member->flags |= CHFL_BAN_CHECKED;
853 adx 30 }
854     }
855 michael 9249 else if (is_banned(channel, client) == true)
856 michael 1941 return ERR_CANNOTSENDTOCHAN;
857     }
858 adx 30
859 michael 9249 return extban_mute_can_send(channel, client, member);
860 adx 30 }
861    
862     /*! \brief Updates the client's oper_warn_count_down, warns the
863     * IRC operators if necessary, and updates
864     * join_leave_countdown as needed.
865 michael 9249 * \param client Pointer to struct Client to check
866     * \param name Channel name or NULL if this is a part.
867 adx 30 */
868     void
869 michael 9249 check_spambot_warning(struct Client *client, const char *name)
870 adx 30 {
871 michael 8273 if (GlobalSetOptions.spam_num &&
872 michael 9249 (client->connection->join_leave_count >= GlobalSetOptions.spam_num))
873 adx 30 {
874 michael 9249 if (client->connection->oper_warn_count_down)
875     --client->connection->oper_warn_count_down;
876 adx 30
877 michael 9249 if (client->connection->oper_warn_count_down == 0)
878 adx 30 {
879 michael 3308 /* It's already known as a possible spambot */
880 michael 3235 if (name)
881 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
882 adx 30 "User %s (%s@%s) trying to join %s is a possible spambot",
883 michael 9249 client->name, client->username,
884     client->host, name);
885 adx 30 else
886 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
887 adx 30 "User %s (%s@%s) is a possible spambot",
888 michael 9249 client->name, client->username,
889     client->host);
890     client->connection->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
891 adx 30 }
892     }
893     else
894     {
895 michael 9249 unsigned int t_delta = event_base->time.sec_monotonic - client->connection->last_leave_time;
896 michael 8275 if (t_delta > JOIN_LEAVE_COUNT_EXPIRE_TIME)
897 adx 30 {
898 michael 8795 unsigned int decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
899 michael 9249 if (decrement_count > client->connection->join_leave_count)
900     client->connection->join_leave_count = 0;
901 adx 30 else
902 michael 9249 client->connection->join_leave_count -= decrement_count;
903 adx 30 }
904     else
905     {
906 michael 9249 if ((event_base->time.sec_monotonic - client->connection->last_join_time) < GlobalSetOptions.spam_time)
907     ++client->connection->join_leave_count; /* It's a possible spambot */
908 adx 30 }
909    
910 michael 3215 if (name)
911 michael 9249 client->connection->last_join_time = event_base->time.sec_monotonic;
912 adx 30 else
913 michael 9249 client->connection->last_leave_time = event_base->time.sec_monotonic;
914 adx 30 }
915     }
916    
917 michael 3308 /*! \brief Sets the channel topic for a certain channel
918 michael 9082 * \param channel Pointer to struct Channel
919 adx 30 * \param topic The topic string
920     * \param topic_info n!u\@h formatted string of the topic setter
921 michael 3308 * \param topicts Timestamp on the topic
922     * \param local Whether the topic is set by a local client
923 adx 30 */
924     void
925 michael 9082 channel_set_topic(struct Channel *channel, const char *topic,
926 michael 8659 const char *topic_info, uintmax_t topicts, bool local)
927 adx 30 {
928 michael 8659 if (local == true)
929 michael 9082 strlcpy(channel->topic, topic, IRCD_MIN(sizeof(channel->topic), ConfigServerInfo.max_topic_length + 1));
930 michael 1751 else
931 michael 9082 strlcpy(channel->topic, topic, sizeof(channel->topic));
932 michael 1751
933 michael 9082 strlcpy(channel->topic_info, topic_info, sizeof(channel->topic_info));
934     channel->topic_time = topicts;
935 adx 30 }
936 michael 3913
937     void
938 michael 9249 channel_do_join(struct Client *client, char *chan_list, char *key_list)
939 michael 3913 {
940     char *p = NULL;
941 michael 7281 const struct ResvItem *resv = NULL;
942 michael 9249 const struct ClassItem *const class = class_get_ptr(&client->connection->confs);
943 michael 3913 unsigned int flags = 0;
944    
945 michael 9249 assert(MyClient(client));
946 michael 5591
947 michael 7907 for (const char *name = strtok_r(chan_list, ",", &p); name;
948     name = strtok_r(NULL, ",", &p))
949 michael 3913 {
950     const char *key = NULL;
951    
952     /* If we have any more keys, take the first for this channel. */
953     if (!EmptyString(key_list) && (key_list = strchr(key = key_list, ',')))
954     *key_list++ = '\0';
955    
956     /* Empty keys are the same as no keys. */
957     if (key && *key == '\0')
958     key = NULL;
959    
960 michael 8659 if (channel_check_name(name, true) == false)
961 michael 3913 {
962 michael 9249 sendto_one_numeric(client, &me, ERR_BADCHANNAME, name);
963 michael 3913 continue;
964     }
965    
966 michael 9249 if (!HasFlag(client, FLAGS_EXEMPTRESV) &&
967     !(HasUMode(client, UMODE_OPER) && HasOFlag(client, OPER_FLAG_JOIN_RESV)) &&
968     ((resv = resv_find(name, match)) && resv_exempt_find(client, resv) == false))
969 michael 3913 {
970 michael 9249 sendto_one_numeric(client, &me, ERR_CHANBANREASON, name, resv->reason);
971 michael 4152 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
972 michael 3913 "Forbidding reserved channel %s from user %s",
973 michael 9249 name, client_get_name(client, HIDE_IP));
974 michael 3913 continue;
975     }
976    
977 michael 9249 if (dlink_list_length(&client->channel) >=
978 michael 3934 ((class->max_channels) ? class->max_channels : ConfigChannel.max_channels))
979 michael 3913 {
980 michael 9249 sendto_one_numeric(client, &me, ERR_TOOMANYCHANNELS, name);
981 michael 3913 break;
982     }
983    
984 michael 9199 struct Channel *channel = hash_find_channel(name);
985     if (channel)
986 michael 3913 {
987 michael 9456 if (member_find_link(client, channel))
988 michael 3913 continue;
989    
990 michael 7556 /* can_join() checks for +i, +l, key, bans, etc. */
991 michael 9249 int ret = can_join(client, channel, key);
992 michael 7556 if (ret)
993 michael 3913 {
994 michael 9249 sendto_one_numeric(client, &me, ret, channel->name);
995 michael 3913 continue;
996     }
997    
998     /*
999     * This should never be the case unless there is some sort of
1000 michael 9249 * persistent channels.
1001 michael 3913 */
1002 michael 9082 if (dlink_list_length(&channel->members) == 0)
1003 michael 3913 flags = CHFL_CHANOP;
1004     else
1005     flags = 0;
1006     }
1007     else
1008     {
1009     flags = CHFL_CHANOP;
1010 michael 9082 channel = channel_make(name);
1011 michael 3913 }
1012    
1013 michael 9249 if (!HasUMode(client, UMODE_OPER))
1014     check_spambot_warning(client, channel->name);
1015 michael 3913
1016 michael 9249 add_user_to_channel(channel, client, flags, true);
1017 michael 3913
1018     /*
1019 michael 5546 * Set timestamp if appropriate, and propagate
1020 michael 3913 */
1021     if (flags == CHFL_CHANOP)
1022     {
1023 michael 9082 channel->creation_time = event_base->time.sec_real;
1024     AddCMode(channel, MODE_TOPICLIMIT);
1025     AddCMode(channel, MODE_NOPRIVMSGS);
1026 michael 3913
1027 michael 8514 sendto_server(NULL, 0, 0, ":%s SJOIN %ju %s +nt :@%s",
1028 michael 9082 me.id, channel->creation_time,
1029 michael 9249 channel->name, client->id);
1030 michael 3913
1031     /*
1032     * Notify all other users on the new channel
1033     */
1034 michael 9082 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
1035 michael 9249 client->name, client->username,
1036     client->host, channel->name, client->account, client->info);
1037 michael 9082 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
1038 michael 9249 client->name, client->username,
1039     client->host, channel->name);
1040 michael 9082 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s MODE %s +nt",
1041     me.name, channel->name);
1042 michael 3913 }
1043     else
1044     {
1045 michael 8514 sendto_server(NULL, 0, 0, ":%s JOIN %ju %s +",
1046 michael 9249 client->id, channel->creation_time,
1047 michael 9082 channel->name);
1048 michael 3913
1049 michael 9082 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
1050 michael 9249 client->name, client->username,
1051     client->host, channel->name, client->account, client->info);
1052 michael 9082 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
1053 michael 9249 client->name, client->username,
1054     client->host, channel->name);
1055 michael 3913 }
1056    
1057 michael 9249 if (client->away[0])
1058     sendto_channel_local(client, channel, 0, CAP_AWAY_NOTIFY, 0,
1059 michael 8541 ":%s!%s@%s AWAY :%s",
1060 michael 9249 client->name, client->username,
1061     client->host, client->away);
1062 michael 8541
1063 michael 9266 struct Invite *invite = invite_find(channel, client);
1064 michael 9199 if (invite)
1065 michael 9266 invite_del(invite);
1066 michael 3913
1067 michael 9082 if (channel->topic[0])
1068 michael 3913 {
1069 michael 9249 sendto_one_numeric(client, &me, RPL_TOPIC, channel->name, channel->topic);
1070     sendto_one_numeric(client, &me, RPL_TOPICWHOTIME, channel->name,
1071 michael 9082 channel->topic_info, channel->topic_time);
1072 michael 3913 }
1073    
1074 michael 9249 channel_member_names(client, channel, true);
1075 michael 3913
1076 michael 9249 client->connection->last_join_time = event_base->time.sec_monotonic;
1077 michael 3913 }
1078     }
1079    
1080     /*! \brief Removes a client from a specific channel
1081 michael 9249 * \param client Pointer to client to remove
1082     * \param name Name of channel to remove from
1083     * \param reason Part reason to show
1084 michael 3913 */
1085     static void
1086 michael 9249 channel_part_one_client(struct Client *client, const char *name, const char *reason)
1087 michael 3913 {
1088 michael 9364 struct Channel *channel = hash_find_channel(name);
1089     if (channel == NULL)
1090 michael 3913 {
1091 michael 9249 sendto_one_numeric(client, &me, ERR_NOSUCHCHANNEL, name);
1092 michael 3913 return;
1093     }
1094    
1095 michael 9456 struct ChannelMember *member = member_find_link(client, channel);
1096 michael 9364 if (member == NULL)
1097 michael 3913 {
1098 michael 9249 sendto_one_numeric(client, &me, ERR_NOTONCHANNEL, channel->name);
1099 michael 3913 return;
1100     }
1101    
1102 michael 9249 if (MyConnect(client) && !HasUMode(client, UMODE_OPER))
1103     check_spambot_warning(client, NULL);
1104 michael 3913
1105     /*
1106 michael 9364 * Remove user from the old channel (if any). Only allow /part reasons in -m chans.
1107 michael 3913 */
1108 michael 9249 if (*reason && (!MyConnect(client) ||
1109     ((client->connection->created_monotonic +
1110 michael 8918 ConfigGeneral.anti_spam_exit_message_time) < event_base->time.sec_monotonic &&
1111 michael 9249 can_send(channel, client, member, reason, false) < 0)))
1112 michael 3913 {
1113 michael 9249 sendto_server(client, 0, 0, ":%s PART %s :%s",
1114     client->id, channel->name, reason);
1115 michael 9082 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s!%s@%s PART %s :%s",
1116 michael 9249 client->name, client->username,
1117     client->host, channel->name, reason);
1118 michael 3913 }
1119     else
1120     {
1121 michael 9249 sendto_server(client, 0, 0, ":%s PART %s",
1122     client->id, channel->name);
1123 michael 9082 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s!%s@%s PART %s",
1124 michael 9249 client->name, client->username,
1125     client->host, channel->name);
1126 michael 3913 }
1127    
1128 michael 4816 remove_user_from_channel(member);
1129 michael 3913 }
1130    
1131     void
1132 michael 9249 channel_do_part(struct Client *client, char *channel, const char *reason)
1133 michael 3913 {
1134 michael 7796 char *p = NULL;
1135 michael 4784 char buf[KICKLEN + 1] = "";
1136 michael 3913
1137 michael 9249 assert(IsClient(client));
1138 michael 5591
1139 michael 3936 if (!EmptyString(reason))
1140 michael 4784 strlcpy(buf, reason, sizeof(buf));
1141 michael 3913
1142 michael 7796 for (const char *name = strtok_r(channel, ",", &p); name;
1143     name = strtok_r(NULL, ",", &p))
1144 michael 9249 channel_part_one_client(client, name, buf);
1145 michael 3913 }

Properties

Name Value
svn:eol-style native
svn:keywords Id