/[svn]/ircd-hybrid/trunk/src/channel.c
ViewVC logotype

Annotation of /ircd-hybrid/trunk/src/channel.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9476 - (hide annotations)
Sat Jul 4 15:26:19 2020 UTC (3 months, 3 weeks ago) by michael
File MIME type: text/x-chdr
File size: 33457 byte(s)
- channel.c:channel_send_namereply(): remove show_eon argument. In hybrid we no longer have a case where a names reply needs to be sent with no RPL_ENDOFNAMES

1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 9101 * 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 4565 * 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 9265 #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 7234 #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 9234 #include "extban.h"
46 adx 30
47 michael 3235
48 michael 8439 /** Doubly linked list containing a list of all channels. */
49     static dlink_list channel_list;
50 adx 30
51    
52 michael 8439 /*! \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 9081 * \param channel Pointer to channel to add client to
64 michael 9250 * \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 9250 add_user_to_channel(struct Channel *channel, struct Client *client,
70 michael 8664 unsigned int flags, bool flood_ctrl)
71 adx 30 {
72 michael 9250 assert(IsClient(client));
73 michael 5590
74 michael 7779 if (GlobalSetOptions.joinfloodtime)
75 adx 30 {
76 michael 8664 if (flood_ctrl == true)
77 michael 9081 ++channel->number_joined;
78 adx 30
79 michael 9081 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 9081 if (channel->number_joined <= 0)
84 adx 30 {
85 michael 9081 channel->number_joined = 0;
86     ClearJoinFloodNoticed(channel);
87 adx 30 }
88 michael 9081 else if (channel->number_joined >= GlobalSetOptions.joinfloodcount)
89 adx 30 {
90 michael 9081 channel->number_joined = GlobalSetOptions.joinfloodcount;
91 adx 30
92 michael 9081 if (!IsSetJoinFloodNoticed(channel))
93 adx 30 {
94 michael 9081 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 9250 client_get_name(client, HIDE_IP),
98     client->servptr->name, channel->name);
99 adx 30 }
100     }
101    
102 michael 9081 channel->last_join_time = event_base->time.sec_monotonic;
103 adx 30 }
104    
105 michael 9081 struct ChannelMember *member = xcalloc(sizeof(*member));
106 michael 9250 member->client = client;
107 michael 9081 member->channel = channel;
108 michael 4815 member->flags = flags;
109 adx 30
110 michael 9081 dlinkAdd(member, &member->channode, &channel->members);
111 michael 4170
112 michael 9250 if (MyConnect(client))
113 michael 9081 dlinkAdd(member, &member->locchannode, &channel->members_local);
114 michael 4170
115 michael 9250 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 9081 remove_user_from_channel(struct ChannelMember *member)
124 adx 30 {
125 michael 9250 struct Client *const client = member->client;
126 michael 9081 struct Channel *const channel = member->channel;
127 adx 30
128 michael 9081 dlinkDelete(&member->channode, &channel->members);
129 michael 4170
130 michael 9250 if (MyConnect(client))
131 michael 9081 dlinkDelete(&member->locchannode, &channel->members_local);
132 michael 4170
133 michael 9250 dlinkDelete(&member->usernode, &client->channel);
134 adx 30
135 michael 8385 xfree(member);
136 adx 30
137 michael 9081 if (channel->members.head == NULL)
138     channel_free(channel);
139 adx 30 }
140    
141 michael 9450 /* 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 6373 /* channel_send_members()
201 adx 30 *
202     * inputs -
203     * output - NONE
204     * side effects -
205     */
206     static void
207 michael 9250 channel_send_members(struct Client *client, const struct Channel *channel,
208 michael 7797 const char *modebuf, const char *parabuf)
209 adx 30 {
210 michael 8059 dlink_node *node;
211 michael 9086 char buf[IRCD_BUFSIZE];
212 adx 30 int tlen; /* length of text to append */
213     char *t, *start; /* temp char pointer */
214    
215 michael 6782 start = t = buf + snprintf(buf, sizeof(buf), ":%s SJOIN %ju %s %s %s:",
216 michael 9081 me.id, channel->creation_time,
217     channel->name, modebuf, parabuf);
218 adx 30
219 michael 9081 DLINK_FOREACH(node, channel->members.head)
220 adx 30 {
221 michael 9081 const struct ChannelMember *member = node->data;
222 adx 30
223 michael 9081 tlen = strlen(member->client->id) + 1; /* +1 for space */
224 michael 9454 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 3782 * 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 9250 sendto_one(client, "%s", buf);
234 adx 30 t = start;
235     }
236    
237 michael 9454 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 9081 if (channel->members.head)
242 michael 8431 --t; /* Take the space out */
243 adx 30 *t = '\0';
244 michael 9250 sendto_one(client, "%s", buf);
245 adx 30 }
246    
247 michael 3308 /*! \brief Sends +b/+e/+I
248 michael 9250 * \param client Client pointer to server
249 michael 9081 * \param channel Pointer to channel
250 michael 3997 * \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 9250 channel_send_mask_list(struct Client *client, const struct Channel *channel,
255 michael 6373 const dlink_list *list, const char flag)
256 adx 30 {
257 michael 7687 dlink_node *node;
258 michael 9086 char mbuf[IRCD_BUFSIZE];
259     char pbuf[IRCD_BUFSIZE];
260 michael 9348 size_t tlen, mlen, cur_len;
261 michael 3144 char *pp = pbuf;
262 adx 30
263 michael 8447 if (dlink_list_length(list) == 0)
264 adx 30 return;
265    
266 michael 6782 mlen = snprintf(mbuf, sizeof(mbuf), ":%s BMASK %ju %s %c :", me.id,
267 michael 9081 channel->creation_time, channel->name, flag);
268 michael 3135 cur_len = mlen;
269 adx 30
270 michael 4800 DLINK_FOREACH(node, list->head)
271 adx 30 {
272 michael 4815 const struct Ban *ban = node->data;
273 adx 30
274 michael 9234 tlen = ban->banstr_len + 1; /* +1 for space */
275 adx 30
276     /*
277 michael 3996 * Send buffer and start over if we cannot fit another ban
278 adx 30 */
279 michael 9348 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 9250 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 9348 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 9250 sendto_one(client, "%s%s", mbuf, pbuf);
294 adx 30 }
295    
296 michael 9250 /*! \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 9250 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 9250 channel_modes(channel, client, modebuf, parabuf);
307     channel_send_members(client, channel, modebuf, parabuf);
308 adx 30
309 michael 9250 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 8660 bool
320     channel_check_name(const char *name, bool local)
321 adx 30 {
322 michael 632 const char *p = name;
323 michael 3421
324 michael 5590 assert(!EmptyString(p));
325 adx 30
326 michael 632 if (!IsChanPrefix(*p))
327 michael 8660 return false;
328 adx 30
329 michael 8660 if (local == false || ConfigChannel.disable_fake_channels == 0)
330 michael 632 {
331     while (*++p)
332 db 634 if (!IsChanChar(*p))
333 michael 8660 return false;
334 michael 632 }
335     else
336     {
337     while (*++p)
338 db 634 if (!IsVisibleChanChar(*p))
339 michael 8660 return false;
340 michael 632 }
341    
342 michael 3421 return p - name <= CHANNELLEN;
343 adx 30 }
344    
345     void
346 michael 4815 remove_ban(struct Ban *ban, dlink_list *list)
347 adx 30 {
348 michael 4815 dlinkDelete(&ban->node, list);
349 michael 8385 xfree(ban);
350 adx 30 }
351    
352 michael 6373 /* channel_free_mask_list()
353 adx 30 *
354     * inputs - pointer to dlink_list
355     * output - NONE
356     * side effects -
357     */
358 michael 6373 static void
359     channel_free_mask_list(dlink_list *list)
360 adx 30 {
361 michael 7266 while (list->head)
362     {
363     struct Ban *ban = list->head->data;
364     remove_ban(ban, list);
365     }
366 adx 30 }
367    
368 michael 4618 /*! \brief Get Channel block for name (and allocate a new channel
369 adx 30 * block, if it didn't exist before)
370 michael 4618 * \param name Channel name
371 michael 3308 * \return Channel block
372 adx 30 */
373     struct Channel *
374 michael 6373 channel_make(const char *name)
375 adx 30 {
376 michael 4618 assert(!EmptyString(name));
377 adx 30
378 michael 9081 struct Channel *channel = xcalloc(sizeof(*channel));
379     channel->hnextch = channel;
380 michael 3308 /* Doesn't hurt to set it here */
381 michael 9081 channel->creation_time = event_base->time.sec_real;
382     channel->last_join_time = event_base->time.sec_monotonic;
383 adx 30
384 michael 8027 /* Cache channel name length to avoid repetitive strlen() calls. */
385 michael 9081 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 6990
389 michael 9081 dlinkAdd(channel, &channel->node, &channel_list);
390     hash_add_channel(channel);
391 adx 30
392 michael 9081 return channel;
393 adx 30 }
394    
395 michael 3308 /*! \brief Walk through this channel, and destroy it.
396 michael 9081 * \param channel Channel pointer
397 adx 30 */
398     void
399 michael 9081 channel_free(struct Channel *channel)
400 adx 30 {
401 michael 9265 invite_clear_list(&channel->invites);
402 adx 30
403 michael 3308 /* Free ban/exception/invex lists */
404 michael 9081 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 9081 dlinkDelete(&channel->node, &channel_list);
409     hash_del_channel(channel);
410 adx 30
411 michael 9081 assert(channel->hnextch == channel);
412 michael 8588
413 michael 9081 assert(channel->node.prev == NULL);
414     assert(channel->node.next == NULL);
415 michael 8588
416 michael 9081 assert(dlink_list_length(&channel->members_local) == 0);
417     assert(channel->members_local.head == NULL);
418     assert(channel->members_local.tail == NULL);
419 michael 8588
420 michael 9081 assert(dlink_list_length(&channel->members) == 0);
421     assert(channel->members.head == NULL);
422     assert(channel->members.tail == NULL);
423 michael 8588
424 michael 9081 assert(dlink_list_length(&channel->invites) == 0);
425     assert(channel->invites.head == NULL);
426     assert(channel->invites.tail == NULL);
427 michael 8588
428 michael 9081 assert(dlink_list_length(&channel->banlist) == 0);
429     assert(channel->banlist.head == NULL);
430     assert(channel->banlist.tail == NULL);
431 michael 8588
432 michael 9081 assert(dlink_list_length(&channel->exceptlist) == 0);
433     assert(channel->exceptlist.head == NULL);
434     assert(channel->exceptlist.tail == NULL);
435 michael 8588
436 michael 9081 assert(dlink_list_length(&channel->invexlist) == 0);
437     assert(channel->invexlist.head == NULL);
438     assert(channel->invexlist.tail == NULL);
439 michael 8588
440 michael 9081 xfree(channel);
441 adx 30 }
442    
443     /*!
444 michael 9081 * \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 9081 channel_pub_or_secret(const struct Channel *channel)
449 adx 30 {
450 michael 9081 if (SecretChannel(channel))
451 adx 30 return "@";
452 michael 9081 if (PrivateChannel(channel))
453 adx 30 return "*";
454     return "=";
455     }
456    
457     /*! \brief lists all names on given channel
458 michael 9250 * \param client Pointer to client struct requesting names
459 michael 9081 * \param channel Pointer to channel block
460 adx 30 */
461     void
462 michael 9476 channel_send_namereply(struct Client *client, struct Channel *channel)
463 adx 30 {
464 michael 7687 dlink_node *node;
465 michael 9086 char buf[IRCD_BUFSIZE + 1];
466 michael 9417 char *bufptr = buf;
467     size_t masklen = 0;
468 michael 9455 bool is_member = member_find_link(client, channel) != NULL;
469 michael 9250 bool multi_prefix = HasCap(client, CAP_MULTI_PREFIX) != 0;
470     bool uhnames = HasCap(client, CAP_UHNAMES) != 0;
471 adx 30
472 michael 9250 assert(IsClient(client));
473 michael 5590
474 michael 9081 if (PubChannel(channel) || is_member == true)
475 adx 30 {
476 michael 9417 /* :me.name 353 source_p->name @ channel->name :+nick1 @nick2 %nick3 ...\r\n */
477     /* 1 23456 789 01 2 3 */
478     size_t len = strlen(me.name) + strlen(client->name) + channel->name_len + 13;
479 adx 30
480 michael 9081 DLINK_FOREACH(node, channel->members.head)
481 adx 30 {
482 michael 9081 const struct ChannelMember *member = node->data;
483 adx 30
484 michael 9081 if (HasUMode(member->client, UMODE_INVISIBLE) && is_member == false)
485 adx 30 continue;
486    
487 michael 8656 if (uhnames == true)
488 michael 9417 masklen = strlen(member->client->name) + strlen(member->client->username) +
489     strlen(member->client->host) + 3; /* +3 for ! + @ + space */
490 michael 8431 else
491 michael 9417 masklen = strlen(member->client->name) + 1; /* +1 for space */
492 adx 30
493 michael 9454 masklen += member_get_prefix_len(member, multi_prefix);
494 michael 506
495 michael 9417 if ((bufptr - buf) + masklen + len > sizeof(buf))
496 adx 30 {
497 michael 9417 *(bufptr - 1) = '\0';
498     sendto_one_numeric(client, &me, RPL_NAMREPLY,
499     channel_pub_or_secret(channel), channel->name, buf);
500     bufptr = buf;
501 adx 30 }
502    
503 michael 8656 if (uhnames == true)
504 michael 9417 bufptr += snprintf(bufptr, sizeof(buf) - (bufptr - buf), "%s%s!%s@%s ",
505 michael 9454 member_get_prefix(member, multi_prefix),
506 michael 9417 member->client->name, member->client->username,
507     member->client->host);
508 michael 8431 else
509 michael 9417 bufptr += snprintf(bufptr, sizeof(buf) - (bufptr - buf), "%s%s ",
510 michael 9454 member_get_prefix(member, multi_prefix),
511 michael 9417 member->client->name);
512 adx 30 }
513    
514 michael 9417 if (bufptr != buf)
515 adx 30 {
516 michael 9417 *(bufptr - 1) = '\0';
517     sendto_one_numeric(client, &me, RPL_NAMREPLY,
518     channel_pub_or_secret(channel), channel->name, buf);
519 adx 30 }
520     }
521    
522 michael 9476 sendto_one_numeric(client, &me, RPL_ENDOFNAMES, channel->name);
523 adx 30 }
524    
525 michael 9454 /* member_get_prefix()
526 adx 30 *
527 michael 9081 * inputs - pointer to struct ChannelMember
528 adx 30 * - YES if we can combine different flags
529     * output - string either @, +, % or "" depending on whether
530     * chanop, voiced or user
531     * side effects -
532     *
533     * NOTE: Returned string is usually a static buffer
534 michael 7997 * (like in client_get_name)
535 adx 30 */
536     const char *
537 michael 9454 member_get_prefix(const struct ChannelMember *member, bool combine)
538 adx 30 {
539 michael 6904 static char buffer[CMEMBER_STATUS_FLAGS_LEN + 1]; /* +1 for \0 */
540 michael 1902 char *p = buffer;
541 adx 30
542 michael 4815 if (member->flags & CHFL_CHANOP)
543 adx 30 {
544 michael 8656 if (combine == false)
545 adx 30 return "@";
546     *p++ = '@';
547     }
548    
549 michael 4815 if (member->flags & CHFL_HALFOP)
550 adx 30 {
551 michael 8656 if (combine == false)
552 adx 30 return "%";
553     *p++ = '%';
554     }
555    
556 michael 4815 if (member->flags & CHFL_VOICE)
557 adx 30 *p++ = '+';
558     *p = '\0';
559    
560     return buffer;
561     }
562    
563 michael 9454 size_t
564     member_get_prefix_len(const struct ChannelMember *member, bool combine)
565     {
566     size_t len = 0;
567    
568     if (member->flags & CHFL_CHANOP)
569     {
570     if (combine == false)
571     return 1;
572     ++len;
573     }
574    
575     if (member->flags & CHFL_HALFOP)
576     {
577     if (combine == false)
578     return 1;
579     ++len;
580     }
581    
582     if (member->flags & CHFL_VOICE)
583     {
584     if (combine == false)
585     return 1;
586     ++len;
587     }
588    
589     return len;
590     }
591    
592 adx 30 /*!
593 michael 9250 * \param client Pointer to Client to check
594     * \param list Pointer to ban list to search
595 adx 30 * \return 1 if ban found for given n!u\@h mask, 0 otherwise
596     */
597 michael 8664 static bool
598 michael 9250 ban_matches(struct Client *client, struct Channel *channel, struct Ban *ban)
599 adx 30 {
600 michael 9234 /* Is a matching extban, call custom match handler */
601     if (ban->extban & extban_matching_mask())
602     {
603     struct Extban *extban = extban_find_flag(ban->extban & extban_matching_mask());
604     if (extban == NULL)
605     return false;
606    
607 michael 9250 if (extban->matches == NULL || extban->matches(client, channel, ban) == EXTBAN_NO_MATCH)
608 michael 9234 return false;
609    
610     return true;
611     }
612    
613 michael 9250 if (match(ban->name, client->name) == 0 && match(ban->user, client->username) == 0)
614 michael 9234 {
615     switch (ban->type)
616     {
617     case HM_HOST:
618 michael 9250 if (match(ban->host, client->realhost) == 0 ||
619     match(ban->host, client->sockhost) == 0 || match(ban->host, client->host) == 0)
620 michael 9234 return true;
621     break;
622     case HM_IPV4:
623 michael 9250 if (client->ip.ss.ss_family == AF_INET)
624     if (match_ipv4(&client->ip, &ban->addr, ban->bits))
625 michael 9234 return true;
626     break;
627     case HM_IPV6:
628 michael 9250 if (client->ip.ss.ss_family == AF_INET6)
629     if (match_ipv6(&client->ip, &ban->addr, ban->bits))
630 michael 9234 return true;
631     break;
632     default:
633     assert(0);
634     }
635     }
636    
637     return false;
638     }
639    
640     bool
641 michael 9250 find_bmask(struct Client *client, struct Channel *channel, const dlink_list *list, struct Extban *extban)
642 michael 9234 {
643 michael 7687 dlink_node *node;
644 adx 30
645 michael 4800 DLINK_FOREACH(node, list->head)
646 adx 30 {
647 michael 9234 struct Ban *ban = node->data;
648 adx 30
649 michael 9234 /* Looking for a specific type of extban? */
650     if (extban)
651 michael 371 {
652 michael 9234 if (!(ban->extban & extban->flag))
653     continue;
654 michael 371 }
655 michael 9234 else
656     {
657     /*
658     * Acting extbans have their own time they act and are not general purpose bans,
659     * so skip them unless we are hunting them.
660     */
661     if (ban->extban & extban_acting_mask())
662     continue;
663     }
664    
665 michael 9250 bool matches = ban_matches(client, channel, ban);
666 michael 9234 if (matches == false)
667     continue;
668    
669     return true;
670 adx 30 }
671    
672 michael 8664 return false;
673 adx 30 }
674    
675     /*!
676 michael 9250 * \param channel Pointer to channel block
677     * \param client Pointer to client to check access fo
678 adx 30 * \return 0 if not banned, 1 otherwise
679     */
680 michael 8664 bool
681 michael 9250 is_banned(struct Channel *channel, struct Client *client)
682 adx 30 {
683 michael 9250 if (find_bmask(client, channel, &channel->banlist, NULL) == true)
684     return find_bmask(client, channel, &channel->exceptlist, NULL) == false;
685 michael 8664 return false;
686 adx 30 }
687    
688 michael 3308 /*! Tests if a client can join a certain channel
689 michael 9250 * \param client Pointer to client attempting to join
690 michael 9081 * \param channel Pointer to channel
691 michael 3308 * \param key Key sent by client attempting to join if present
692 adx 30 * \return ERR_BANNEDFROMCHAN, ERR_INVITEONLYCHAN, ERR_CHANNELISFULL
693     * or 0 if allowed to join.
694     */
695 michael 6881 static int
696 michael 9250 can_join(struct Client *client, struct Channel *channel, const char *key)
697 adx 30 {
698 michael 9250 if (HasCMode(channel, MODE_SECUREONLY) && !HasUMode(client, UMODE_SECURE))
699 michael 9157 return ERR_SECUREONLYCHAN;
700 michael 1150
701 michael 9250 if (HasCMode(channel, MODE_REGONLY) && !HasUMode(client, UMODE_REGISTERED))
702 michael 1173 return ERR_NEEDREGGEDNICK;
703    
704 michael 9250 if (HasCMode(channel, MODE_OPERONLY) && !HasUMode(client, UMODE_OPER))
705 michael 1150 return ERR_OPERONLYCHAN;
706    
707 michael 9081 if (HasCMode(channel, MODE_INVITEONLY))
708 michael 9265 if (invite_find(channel, client) == NULL)
709 michael 9250 if (find_bmask(client, channel, &channel->invexlist, NULL) == false)
710 adx 30 return ERR_INVITEONLYCHAN;
711    
712 michael 9081 if (channel->mode.key[0] && (key == NULL || strcmp(channel->mode.key, key)))
713 adx 30 return ERR_BADCHANNELKEY;
714    
715 michael 9081 if (channel->mode.limit && dlink_list_length(&channel->members) >=
716     channel->mode.limit)
717 adx 30 return ERR_CHANNELISFULL;
718    
719 michael 9250 if (is_banned(channel, client) == true)
720 michael 2208 return ERR_BANNEDFROMCHAN;
721    
722 michael 9250 return extban_join_can_join(channel, client, NULL);
723 adx 30 }
724    
725     int
726 michael 9081 has_member_flags(const struct ChannelMember *member, const unsigned int flags)
727 adx 30 {
728 michael 4815 return member && (member->flags & flags);
729 adx 30 }
730    
731 michael 9081 struct ChannelMember *
732 michael 9455 member_find_link(const struct Client *client, const struct Channel *channel)
733 adx 30 {
734 michael 7914 dlink_node *node;
735 adx 30
736 michael 9250 if (!IsClient(client))
737 adx 30 return NULL;
738    
739 michael 8439 /* Take the shortest of the two lists */
740 michael 9250 if (dlink_list_length(&channel->members) < dlink_list_length(&client->channel))
741 michael 2567 {
742 michael 9081 DLINK_FOREACH(node, channel->members.head)
743 michael 9250 if (((struct ChannelMember *)node->data)->client == client)
744 michael 4800 return node->data;
745 michael 2567 }
746     else
747     {
748 michael 9250 DLINK_FOREACH(node, client->channel.head)
749 michael 9081 if (((struct ChannelMember *)node->data)->channel == channel)
750 michael 4800 return node->data;
751 michael 2567 }
752 adx 30
753     return NULL;
754     }
755    
756 michael 4783 /*! Checks if a message contains control codes
757 michael 3888 * \param message The actual message string the client wants to send
758     * \return 1 if the message does contain any control codes, 0 otherwise
759 michael 1937 */
760 michael 8658 static bool
761 michael 1937 msg_has_ctrls(const char *message)
762     {
763 michael 9356 const unsigned char *p = (const unsigned char *)message;
764    
765     for (; *p; ++p)
766 michael 1937 {
767     if (*p > 31 || *p == 1)
768 michael 3952 continue; /* No control code or CTCP */
769 michael 1937
770 michael 3888 if (*p == 27) /* Escape */
771 michael 1937 {
772 michael 3888 /* ISO 2022 charset shift sequence */
773 michael 1937 if (*(p + 1) == '$' ||
774     *(p + 1) == '(')
775     {
776     ++p;
777     continue;
778     }
779     }
780    
781 michael 8658 return true; /* Control code */
782 michael 1937 }
783    
784 michael 8658 return false; /* No control code found */
785 michael 1937 }
786    
787 michael 3308 /*! Tests if a client can send to a channel
788 michael 9250 * \param channel Pointer to Channel struct
789     * \param client Pointer to Client struct
790     * \param member Pointer to Membership struct (can be NULL)
791     * \param message The actual message string the client wants to send
792 adx 30 * \return CAN_SEND_OPV if op or voiced on channel\n
793     * CAN_SEND_NONOP if can send to channel but is not an op\n
794 michael 1173 * ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
795 adx 30 */
796     int
797 michael 9250 can_send(struct Channel *channel, struct Client *client,
798 michael 9081 struct ChannelMember *member, const char *message, bool notice)
799 adx 30 {
800 michael 9086 const struct ResvItem *resv;
801 michael 1858
802 michael 9250 if (IsServer(client) || HasFlag(client, FLAGS_SERVICE))
803 adx 30 return CAN_SEND_OPV;
804    
805 michael 9250 if (MyConnect(client) && !HasFlag(client, FLAGS_EXEMPTRESV))
806     if (!(HasUMode(client, UMODE_OPER) && HasOFlag(client, OPER_FLAG_JOIN_RESV)))
807     if ((resv = resv_find(channel->name, match)) && resv_exempt_find(client, resv) == false)
808 michael 1834 return ERR_CANNOTSENDTOCHAN;
809 adx 30
810 michael 9081 if (HasCMode(channel, MODE_NOCTRL) && msg_has_ctrls(message) == true)
811 michael 1944 return ERR_NOCTRLSONCHAN;
812 michael 4884
813 michael 9081 if (HasCMode(channel, MODE_NOCTCP))
814 michael 5465 if (*message == '\001' && strncmp(message + 1, "ACTION ", 7))
815 michael 5464 return ERR_NOCTCP;
816    
817 michael 9455 if (member || (member = member_find_link(client, channel)))
818 michael 5583 if (member->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
819 adx 30 return CAN_SEND_OPV;
820 michael 4884
821 michael 9081 if (member == NULL && HasCMode(channel, MODE_NOPRIVMSGS))
822 michael 2441 return ERR_CANNOTSENDTOCHAN;
823 michael 4884
824 michael 9081 if (HasCMode(channel, MODE_MODERATED))
825 michael 1944 return ERR_CANNOTSENDTOCHAN;
826 michael 4884
827 michael 9250 if (HasCMode(channel, MODE_MODREG) && !HasUMode(client, UMODE_REGISTERED))
828 michael 1944 return ERR_NEEDREGGEDNICK;
829 adx 30
830 michael 9081 if (HasCMode(channel, MODE_NONOTICE) && notice == true)
831 michael 6858 return ERR_CANNOTSENDTOCHAN;
832    
833 michael 3308 /* Cache can send if banned */
834 michael 9250 if (MyConnect(client))
835 michael 1944 {
836 michael 4815 if (member)
837 adx 30 {
838 michael 4815 if (member->flags & CHFL_BAN_SILENCED)
839 michael 1834 return ERR_CANNOTSENDTOCHAN;
840 adx 30
841 michael 4815 if (!(member->flags & CHFL_BAN_CHECKED))
842 adx 30 {
843 michael 9250 if (is_banned(channel, client) == true)
844 adx 30 {
845 michael 5583 member->flags |= (CHFL_BAN_CHECKED | CHFL_BAN_SILENCED);
846 michael 1834 return ERR_CANNOTSENDTOCHAN;
847 adx 30 }
848    
849 michael 4815 member->flags |= CHFL_BAN_CHECKED;
850 adx 30 }
851     }
852 michael 9250 else if (is_banned(channel, client) == true)
853 michael 1941 return ERR_CANNOTSENDTOCHAN;
854     }
855 adx 30
856 michael 9250 return extban_mute_can_send(channel, client, member);
857 adx 30 }
858    
859     /*! \brief Updates the client's oper_warn_count_down, warns the
860     * IRC operators if necessary, and updates
861     * join_leave_countdown as needed.
862 michael 9250 * \param client Pointer to struct Client to check
863     * \param name Channel name or NULL if this is a part.
864 adx 30 */
865     void
866 michael 9250 check_spambot_warning(struct Client *client, const char *name)
867 adx 30 {
868 michael 8274 if (GlobalSetOptions.spam_num &&
869 michael 9250 (client->connection->join_leave_count >= GlobalSetOptions.spam_num))
870 adx 30 {
871 michael 9250 if (client->connection->oper_warn_count_down)
872     --client->connection->oper_warn_count_down;
873 adx 30
874 michael 9250 if (client->connection->oper_warn_count_down == 0)
875 adx 30 {
876 michael 3308 /* It's already known as a possible spambot */
877 michael 3235 if (name)
878 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
879 adx 30 "User %s (%s@%s) trying to join %s is a possible spambot",
880 michael 9250 client->name, client->username,
881     client->host, name);
882 adx 30 else
883 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
884 adx 30 "User %s (%s@%s) is a possible spambot",
885 michael 9250 client->name, client->username,
886     client->host);
887     client->connection->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
888 adx 30 }
889     }
890     else
891     {
892 michael 9250 unsigned int t_delta = event_base->time.sec_monotonic - client->connection->last_leave_time;
893 michael 8276 if (t_delta > JOIN_LEAVE_COUNT_EXPIRE_TIME)
894 adx 30 {
895 michael 8796 unsigned int decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
896 michael 9250 if (decrement_count > client->connection->join_leave_count)
897     client->connection->join_leave_count = 0;
898 adx 30 else
899 michael 9250 client->connection->join_leave_count -= decrement_count;
900 adx 30 }
901     else
902     {
903 michael 9250 if ((event_base->time.sec_monotonic - client->connection->last_join_time) < GlobalSetOptions.spam_time)
904     ++client->connection->join_leave_count; /* It's a possible spambot */
905 adx 30 }
906    
907 michael 3215 if (name)
908 michael 9250 client->connection->last_join_time = event_base->time.sec_monotonic;
909 adx 30 else
910 michael 9250 client->connection->last_leave_time = event_base->time.sec_monotonic;
911 adx 30 }
912     }
913    
914 michael 3308 /*! \brief Sets the channel topic for a certain channel
915 michael 9081 * \param channel Pointer to struct Channel
916 adx 30 * \param topic The topic string
917     * \param topic_info n!u\@h formatted string of the topic setter
918 michael 3308 * \param topicts Timestamp on the topic
919     * \param local Whether the topic is set by a local client
920 adx 30 */
921     void
922 michael 9081 channel_set_topic(struct Channel *channel, const char *topic,
923 michael 8660 const char *topic_info, uintmax_t topicts, bool local)
924 adx 30 {
925 michael 8660 if (local == true)
926 michael 9081 strlcpy(channel->topic, topic, IRCD_MIN(sizeof(channel->topic), ConfigServerInfo.max_topic_length + 1));
927 michael 1751 else
928 michael 9081 strlcpy(channel->topic, topic, sizeof(channel->topic));
929 michael 1751
930 michael 9081 strlcpy(channel->topic_info, topic_info, sizeof(channel->topic_info));
931     channel->topic_time = topicts;
932 adx 30 }
933 michael 3912
934     void
935 michael 9250 channel_do_join(struct Client *client, char *chan_list, char *key_list)
936 michael 3912 {
937     char *p = NULL;
938 michael 7282 const struct ResvItem *resv = NULL;
939 michael 9250 const struct ClassItem *const class = class_get_ptr(&client->connection->confs);
940 michael 3912 unsigned int flags = 0;
941    
942 michael 9250 assert(MyClient(client));
943 michael 5590
944 michael 7908 for (const char *name = strtok_r(chan_list, ",", &p); name;
945     name = strtok_r(NULL, ",", &p))
946 michael 3912 {
947     const char *key = NULL;
948    
949     /* If we have any more keys, take the first for this channel. */
950     if (!EmptyString(key_list) && (key_list = strchr(key = key_list, ',')))
951     *key_list++ = '\0';
952    
953     /* Empty keys are the same as no keys. */
954     if (key && *key == '\0')
955     key = NULL;
956    
957 michael 8660 if (channel_check_name(name, true) == false)
958 michael 3912 {
959 michael 9250 sendto_one_numeric(client, &me, ERR_BADCHANNAME, name);
960 michael 3912 continue;
961     }
962    
963 michael 9250 if (!HasFlag(client, FLAGS_EXEMPTRESV) &&
964     !(HasUMode(client, UMODE_OPER) && HasOFlag(client, OPER_FLAG_JOIN_RESV)) &&
965     ((resv = resv_find(name, match)) && resv_exempt_find(client, resv) == false))
966 michael 3912 {
967 michael 9250 sendto_one_numeric(client, &me, ERR_CHANBANREASON, name, resv->reason);
968 michael 4151 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
969 michael 3912 "Forbidding reserved channel %s from user %s",
970 michael 9250 name, client_get_name(client, HIDE_IP));
971 michael 3912 continue;
972     }
973    
974 michael 9250 if (dlink_list_length(&client->channel) >=
975 michael 3933 ((class->max_channels) ? class->max_channels : ConfigChannel.max_channels))
976 michael 3912 {
977 michael 9250 sendto_one_numeric(client, &me, ERR_TOOMANYCHANNELS, name);
978 michael 3912 break;
979     }
980    
981 michael 9200 struct Channel *channel = hash_find_channel(name);
982     if (channel)
983 michael 3912 {
984 michael 9455 if (member_find_link(client, channel))
985 michael 3912 continue;
986    
987 michael 7557 /* can_join() checks for +i, +l, key, bans, etc. */
988 michael 9250 int ret = can_join(client, channel, key);
989 michael 7557 if (ret)
990 michael 3912 {
991 michael 9250 sendto_one_numeric(client, &me, ret, channel->name);
992 michael 3912 continue;
993     }
994    
995     /*
996     * This should never be the case unless there is some sort of
997 michael 9250 * persistent channels.
998 michael 3912 */
999 michael 9081 if (dlink_list_length(&channel->members) == 0)
1000 michael 3912 flags = CHFL_CHANOP;
1001     else
1002     flags = 0;
1003     }
1004     else
1005     {
1006     flags = CHFL_CHANOP;
1007 michael 9081 channel = channel_make(name);
1008 michael 3912 }
1009    
1010 michael 9250 if (!HasUMode(client, UMODE_OPER))
1011     check_spambot_warning(client, channel->name);
1012 michael 3912
1013 michael 9250 add_user_to_channel(channel, client, flags, true);
1014 michael 3912
1015     /*
1016 michael 5545 * Set timestamp if appropriate, and propagate
1017 michael 3912 */
1018     if (flags == CHFL_CHANOP)
1019     {
1020 michael 9081 channel->creation_time = event_base->time.sec_real;
1021     AddCMode(channel, MODE_TOPICLIMIT);
1022     AddCMode(channel, MODE_NOPRIVMSGS);
1023 michael 3912
1024 michael 8513 sendto_server(NULL, 0, 0, ":%s SJOIN %ju %s +nt :@%s",
1025 michael 9081 me.id, channel->creation_time,
1026 michael 9250 channel->name, client->id);
1027 michael 3912
1028     /*
1029     * Notify all other users on the new channel
1030     */
1031 michael 9081 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
1032 michael 9250 client->name, client->username,
1033     client->host, channel->name, client->account, client->info);
1034 michael 9081 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
1035 michael 9250 client->name, client->username,
1036     client->host, channel->name);
1037 michael 9081 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s MODE %s +nt",
1038     me.name, channel->name);
1039 michael 3912 }
1040     else
1041     {
1042 michael 8513 sendto_server(NULL, 0, 0, ":%s JOIN %ju %s +",
1043 michael 9250 client->id, channel->creation_time,
1044 michael 9081 channel->name);
1045 michael 3912
1046 michael 9081 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
1047 michael 9250 client->name, client->username,
1048     client->host, channel->name, client->account, client->info);
1049 michael 9081 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
1050 michael 9250 client->name, client->username,
1051     client->host, channel->name);
1052 michael 3912 }
1053    
1054 michael 9250 if (client->away[0])
1055     sendto_channel_local(client, channel, 0, CAP_AWAY_NOTIFY, 0,
1056 michael 8542 ":%s!%s@%s AWAY :%s",
1057 michael 9250 client->name, client->username,
1058     client->host, client->away);
1059 michael 8542
1060 michael 9265 struct Invite *invite = invite_find(channel, client);
1061 michael 9200 if (invite)
1062 michael 9265 invite_del(invite);
1063 michael 3912
1064 michael 9081 if (channel->topic[0])
1065 michael 3912 {
1066 michael 9250 sendto_one_numeric(client, &me, RPL_TOPIC, channel->name, channel->topic);
1067     sendto_one_numeric(client, &me, RPL_TOPICWHOTIME, channel->name,
1068 michael 9081 channel->topic_info, channel->topic_time);
1069 michael 3912 }
1070    
1071 michael 9476 channel_send_namereply(client, channel);
1072 michael 3912
1073 michael 9250 client->connection->last_join_time = event_base->time.sec_monotonic;
1074 michael 3912 }
1075     }
1076    
1077     /*! \brief Removes a client from a specific channel
1078 michael 9250 * \param client Pointer to client to remove
1079     * \param name Name of channel to remove from
1080     * \param reason Part reason to show
1081 michael 3912 */
1082     static void
1083 michael 9250 channel_part_one_client(struct Client *client, const char *name, const char *reason)
1084 michael 3912 {
1085 michael 9365 struct Channel *channel = hash_find_channel(name);
1086     if (channel == NULL)
1087 michael 3912 {
1088 michael 9250 sendto_one_numeric(client, &me, ERR_NOSUCHCHANNEL, name);
1089 michael 3912 return;
1090     }
1091    
1092 michael 9455 struct ChannelMember *member = member_find_link(client, channel);
1093 michael 9365 if (member == NULL)
1094 michael 3912 {
1095 michael 9250 sendto_one_numeric(client, &me, ERR_NOTONCHANNEL, channel->name);
1096 michael 3912 return;
1097     }
1098    
1099 michael 9250 if (MyConnect(client) && !HasUMode(client, UMODE_OPER))
1100     check_spambot_warning(client, NULL);
1101 michael 3912
1102     /*
1103 michael 9365 * Remove user from the old channel (if any). Only allow /part reasons in -m chans.
1104 michael 3912 */
1105 michael 9250 if (*reason && (!MyConnect(client) ||
1106     ((client->connection->created_monotonic +
1107 michael 8919 ConfigGeneral.anti_spam_exit_message_time) < event_base->time.sec_monotonic &&
1108 michael 9250 can_send(channel, client, member, reason, false) < 0)))
1109 michael 3912 {
1110 michael 9250 sendto_server(client, 0, 0, ":%s PART %s :%s",
1111     client->id, channel->name, reason);
1112 michael 9081 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s!%s@%s PART %s :%s",
1113 michael 9250 client->name, client->username,
1114     client->host, channel->name, reason);
1115 michael 3912 }
1116     else
1117     {
1118 michael 9250 sendto_server(client, 0, 0, ":%s PART %s",
1119     client->id, channel->name);
1120 michael 9081 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s!%s@%s PART %s",
1121 michael 9250 client->name, client->username,
1122     client->host, channel->name);
1123 michael 3912 }
1124    
1125 michael 4815 remove_user_from_channel(member);
1126 michael 3912 }
1127    
1128     void
1129 michael 9250 channel_do_part(struct Client *client, char *channel, const char *reason)
1130 michael 3912 {
1131 michael 7797 char *p = NULL;
1132 michael 4785 char buf[KICKLEN + 1] = "";
1133 michael 3912
1134 michael 9250 assert(IsClient(client));
1135 michael 5590
1136 michael 3937 if (!EmptyString(reason))
1137 michael 4785 strlcpy(buf, reason, sizeof(buf));
1138 michael 3912
1139 michael 7797 for (const char *name = strtok_r(channel, ",", &p); name;
1140     name = strtok_r(NULL, ",", &p))
1141 michael 9250 channel_part_one_client(client, name, buf);
1142 michael 3912 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28