ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel.c
Revision: 9596
Committed: Fri Sep 4 16:51:08 2020 UTC (6 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 33275 byte(s)
Log Message:
- Cleanup ip address matching routine in various places

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 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 9546 channel_modes(channel, client, NULL, modebuf, parabuf);
307 michael 9250 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 9587 /* :me.name 353 client->name @ channel->name :+nick1 @nick2 %nick3 ...\r\n */
477     /* 1 23456 789 01 2 3 */
478 michael 9417 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 michael 9596 case HM_IPV6:
623 michael 9234 case HM_IPV4:
624 michael 9596 if (address_compare(&client->ip, &ban->addr, false, false, ban->bits))
625     return true;
626 michael 9234 break;
627     default:
628     assert(0);
629     }
630     }
631    
632     return false;
633     }
634    
635     bool
636 michael 9250 find_bmask(struct Client *client, struct Channel *channel, const dlink_list *list, struct Extban *extban)
637 michael 9234 {
638 michael 7687 dlink_node *node;
639 adx 30
640 michael 4800 DLINK_FOREACH(node, list->head)
641 adx 30 {
642 michael 9234 struct Ban *ban = node->data;
643 adx 30
644 michael 9234 /* Looking for a specific type of extban? */
645     if (extban)
646 michael 371 {
647 michael 9234 if (!(ban->extban & extban->flag))
648     continue;
649 michael 371 }
650 michael 9234 else
651     {
652     /*
653     * Acting extbans have their own time they act and are not general purpose bans,
654     * so skip them unless we are hunting them.
655     */
656     if (ban->extban & extban_acting_mask())
657     continue;
658     }
659    
660 michael 9250 bool matches = ban_matches(client, channel, ban);
661 michael 9234 if (matches == false)
662     continue;
663    
664     return true;
665 adx 30 }
666    
667 michael 8664 return false;
668 adx 30 }
669    
670     /*!
671 michael 9250 * \param channel Pointer to channel block
672     * \param client Pointer to client to check access fo
673 adx 30 * \return 0 if not banned, 1 otherwise
674     */
675 michael 8664 bool
676 michael 9250 is_banned(struct Channel *channel, struct Client *client)
677 adx 30 {
678 michael 9250 if (find_bmask(client, channel, &channel->banlist, NULL) == true)
679     return find_bmask(client, channel, &channel->exceptlist, NULL) == false;
680 michael 8664 return false;
681 adx 30 }
682    
683 michael 3308 /*! Tests if a client can join a certain channel
684 michael 9250 * \param client Pointer to client attempting to join
685 michael 9081 * \param channel Pointer to channel
686 michael 3308 * \param key Key sent by client attempting to join if present
687 adx 30 * \return ERR_BANNEDFROMCHAN, ERR_INVITEONLYCHAN, ERR_CHANNELISFULL
688     * or 0 if allowed to join.
689     */
690 michael 6881 static int
691 michael 9250 can_join(struct Client *client, struct Channel *channel, const char *key)
692 adx 30 {
693 michael 9250 if (HasCMode(channel, MODE_SECUREONLY) && !HasUMode(client, UMODE_SECURE))
694 michael 9157 return ERR_SECUREONLYCHAN;
695 michael 1150
696 michael 9250 if (HasCMode(channel, MODE_REGONLY) && !HasUMode(client, UMODE_REGISTERED))
697 michael 1173 return ERR_NEEDREGGEDNICK;
698    
699 michael 9250 if (HasCMode(channel, MODE_OPERONLY) && !HasUMode(client, UMODE_OPER))
700 michael 1150 return ERR_OPERONLYCHAN;
701    
702 michael 9081 if (HasCMode(channel, MODE_INVITEONLY))
703 michael 9265 if (invite_find(channel, client) == NULL)
704 michael 9250 if (find_bmask(client, channel, &channel->invexlist, NULL) == false)
705 adx 30 return ERR_INVITEONLYCHAN;
706    
707 michael 9081 if (channel->mode.key[0] && (key == NULL || strcmp(channel->mode.key, key)))
708 adx 30 return ERR_BADCHANNELKEY;
709    
710 michael 9081 if (channel->mode.limit && dlink_list_length(&channel->members) >=
711     channel->mode.limit)
712 adx 30 return ERR_CHANNELISFULL;
713    
714 michael 9250 if (is_banned(channel, client) == true)
715 michael 2208 return ERR_BANNEDFROMCHAN;
716    
717 michael 9250 return extban_join_can_join(channel, client, NULL);
718 adx 30 }
719    
720     int
721 michael 9081 has_member_flags(const struct ChannelMember *member, const unsigned int flags)
722 adx 30 {
723 michael 4815 return member && (member->flags & flags);
724 adx 30 }
725    
726 michael 9081 struct ChannelMember *
727 michael 9455 member_find_link(const struct Client *client, const struct Channel *channel)
728 adx 30 {
729 michael 7914 dlink_node *node;
730 adx 30
731 michael 9250 if (!IsClient(client))
732 adx 30 return NULL;
733    
734 michael 8439 /* Take the shortest of the two lists */
735 michael 9250 if (dlink_list_length(&channel->members) < dlink_list_length(&client->channel))
736 michael 2567 {
737 michael 9081 DLINK_FOREACH(node, channel->members.head)
738 michael 9250 if (((struct ChannelMember *)node->data)->client == client)
739 michael 4800 return node->data;
740 michael 2567 }
741     else
742     {
743 michael 9250 DLINK_FOREACH(node, client->channel.head)
744 michael 9081 if (((struct ChannelMember *)node->data)->channel == channel)
745 michael 4800 return node->data;
746 michael 2567 }
747 adx 30
748     return NULL;
749     }
750    
751 michael 4783 /*! Checks if a message contains control codes
752 michael 3888 * \param message The actual message string the client wants to send
753     * \return 1 if the message does contain any control codes, 0 otherwise
754 michael 1937 */
755 michael 8658 static bool
756 michael 1937 msg_has_ctrls(const char *message)
757     {
758 michael 9356 const unsigned char *p = (const unsigned char *)message;
759    
760     for (; *p; ++p)
761 michael 1937 {
762     if (*p > 31 || *p == 1)
763 michael 3952 continue; /* No control code or CTCP */
764 michael 1937
765 michael 3888 if (*p == 27) /* Escape */
766 michael 1937 {
767 michael 3888 /* ISO 2022 charset shift sequence */
768 michael 1937 if (*(p + 1) == '$' ||
769     *(p + 1) == '(')
770     {
771     ++p;
772     continue;
773     }
774     }
775    
776 michael 8658 return true; /* Control code */
777 michael 1937 }
778    
779 michael 8658 return false; /* No control code found */
780 michael 1937 }
781    
782 michael 3308 /*! Tests if a client can send to a channel
783 michael 9250 * \param channel Pointer to Channel struct
784     * \param client Pointer to Client struct
785     * \param member Pointer to Membership struct (can be NULL)
786     * \param message The actual message string the client wants to send
787 adx 30 * \return CAN_SEND_OPV if op or voiced on channel\n
788     * CAN_SEND_NONOP if can send to channel but is not an op\n
789 michael 1173 * ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
790 adx 30 */
791     int
792 michael 9250 can_send(struct Channel *channel, struct Client *client,
793 michael 9081 struct ChannelMember *member, const char *message, bool notice)
794 adx 30 {
795 michael 9086 const struct ResvItem *resv;
796 michael 1858
797 michael 9250 if (IsServer(client) || HasFlag(client, FLAGS_SERVICE))
798 adx 30 return CAN_SEND_OPV;
799    
800 michael 9250 if (MyConnect(client) && !HasFlag(client, FLAGS_EXEMPTRESV))
801     if (!(HasUMode(client, UMODE_OPER) && HasOFlag(client, OPER_FLAG_JOIN_RESV)))
802     if ((resv = resv_find(channel->name, match)) && resv_exempt_find(client, resv) == false)
803 michael 1834 return ERR_CANNOTSENDTOCHAN;
804 adx 30
805 michael 9081 if (HasCMode(channel, MODE_NOCTRL) && msg_has_ctrls(message) == true)
806 michael 1944 return ERR_NOCTRLSONCHAN;
807 michael 4884
808 michael 9081 if (HasCMode(channel, MODE_NOCTCP))
809 michael 5465 if (*message == '\001' && strncmp(message + 1, "ACTION ", 7))
810 michael 5464 return ERR_NOCTCP;
811    
812 michael 9455 if (member || (member = member_find_link(client, channel)))
813 michael 5583 if (member->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
814 adx 30 return CAN_SEND_OPV;
815 michael 4884
816 michael 9081 if (member == NULL && HasCMode(channel, MODE_NOPRIVMSGS))
817 michael 2441 return ERR_CANNOTSENDTOCHAN;
818 michael 4884
819 michael 9081 if (HasCMode(channel, MODE_MODERATED))
820 michael 1944 return ERR_CANNOTSENDTOCHAN;
821 michael 4884
822 michael 9250 if (HasCMode(channel, MODE_MODREG) && !HasUMode(client, UMODE_REGISTERED))
823 michael 1944 return ERR_NEEDREGGEDNICK;
824 adx 30
825 michael 9081 if (HasCMode(channel, MODE_NONOTICE) && notice == true)
826 michael 6858 return ERR_CANNOTSENDTOCHAN;
827    
828 michael 3308 /* Cache can send if banned */
829 michael 9250 if (MyConnect(client))
830 michael 1944 {
831 michael 4815 if (member)
832 adx 30 {
833 michael 4815 if (member->flags & CHFL_BAN_SILENCED)
834 michael 1834 return ERR_CANNOTSENDTOCHAN;
835 adx 30
836 michael 4815 if (!(member->flags & CHFL_BAN_CHECKED))
837 adx 30 {
838 michael 9250 if (is_banned(channel, client) == true)
839 adx 30 {
840 michael 5583 member->flags |= (CHFL_BAN_CHECKED | CHFL_BAN_SILENCED);
841 michael 1834 return ERR_CANNOTSENDTOCHAN;
842 adx 30 }
843    
844 michael 4815 member->flags |= CHFL_BAN_CHECKED;
845 adx 30 }
846     }
847 michael 9250 else if (is_banned(channel, client) == true)
848 michael 1941 return ERR_CANNOTSENDTOCHAN;
849     }
850 adx 30
851 michael 9250 return extban_mute_can_send(channel, client, member);
852 adx 30 }
853    
854     /*! \brief Updates the client's oper_warn_count_down, warns the
855     * IRC operators if necessary, and updates
856     * join_leave_countdown as needed.
857 michael 9250 * \param client Pointer to struct Client to check
858     * \param name Channel name or NULL if this is a part.
859 adx 30 */
860     void
861 michael 9250 check_spambot_warning(struct Client *client, const char *name)
862 adx 30 {
863 michael 8274 if (GlobalSetOptions.spam_num &&
864 michael 9250 (client->connection->join_leave_count >= GlobalSetOptions.spam_num))
865 adx 30 {
866 michael 9250 if (client->connection->oper_warn_count_down)
867     --client->connection->oper_warn_count_down;
868 adx 30
869 michael 9250 if (client->connection->oper_warn_count_down == 0)
870 adx 30 {
871 michael 3308 /* It's already known as a possible spambot */
872 michael 3235 if (name)
873 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
874 adx 30 "User %s (%s@%s) trying to join %s is a possible spambot",
875 michael 9250 client->name, client->username,
876     client->host, name);
877 adx 30 else
878 michael 1618 sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
879 adx 30 "User %s (%s@%s) is a possible spambot",
880 michael 9250 client->name, client->username,
881     client->host);
882     client->connection->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
883 adx 30 }
884     }
885     else
886     {
887 michael 9250 unsigned int t_delta = event_base->time.sec_monotonic - client->connection->last_leave_time;
888 michael 8276 if (t_delta > JOIN_LEAVE_COUNT_EXPIRE_TIME)
889 adx 30 {
890 michael 8796 unsigned int decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
891 michael 9250 if (decrement_count > client->connection->join_leave_count)
892     client->connection->join_leave_count = 0;
893 adx 30 else
894 michael 9250 client->connection->join_leave_count -= decrement_count;
895 adx 30 }
896     else
897     {
898 michael 9250 if ((event_base->time.sec_monotonic - client->connection->last_join_time) < GlobalSetOptions.spam_time)
899     ++client->connection->join_leave_count; /* It's a possible spambot */
900 adx 30 }
901    
902 michael 3215 if (name)
903 michael 9250 client->connection->last_join_time = event_base->time.sec_monotonic;
904 adx 30 else
905 michael 9250 client->connection->last_leave_time = event_base->time.sec_monotonic;
906 adx 30 }
907     }
908    
909 michael 3308 /*! \brief Sets the channel topic for a certain channel
910 michael 9081 * \param channel Pointer to struct Channel
911 adx 30 * \param topic The topic string
912     * \param topic_info n!u\@h formatted string of the topic setter
913 michael 3308 * \param topicts Timestamp on the topic
914     * \param local Whether the topic is set by a local client
915 adx 30 */
916     void
917 michael 9081 channel_set_topic(struct Channel *channel, const char *topic,
918 michael 8660 const char *topic_info, uintmax_t topicts, bool local)
919 adx 30 {
920 michael 8660 if (local == true)
921 michael 9081 strlcpy(channel->topic, topic, IRCD_MIN(sizeof(channel->topic), ConfigServerInfo.max_topic_length + 1));
922 michael 1751 else
923 michael 9081 strlcpy(channel->topic, topic, sizeof(channel->topic));
924 michael 1751
925 michael 9081 strlcpy(channel->topic_info, topic_info, sizeof(channel->topic_info));
926     channel->topic_time = topicts;
927 adx 30 }
928 michael 3912
929     void
930 michael 9250 channel_do_join(struct Client *client, char *chan_list, char *key_list)
931 michael 3912 {
932     char *p = NULL;
933 michael 7282 const struct ResvItem *resv = NULL;
934 michael 9250 const struct ClassItem *const class = class_get_ptr(&client->connection->confs);
935 michael 3912 unsigned int flags = 0;
936    
937 michael 9250 assert(MyClient(client));
938 michael 5590
939 michael 7908 for (const char *name = strtok_r(chan_list, ",", &p); name;
940     name = strtok_r(NULL, ",", &p))
941 michael 3912 {
942     const char *key = NULL;
943    
944     /* If we have any more keys, take the first for this channel. */
945     if (!EmptyString(key_list) && (key_list = strchr(key = key_list, ',')))
946     *key_list++ = '\0';
947    
948     /* Empty keys are the same as no keys. */
949     if (key && *key == '\0')
950     key = NULL;
951    
952 michael 8660 if (channel_check_name(name, true) == false)
953 michael 3912 {
954 michael 9250 sendto_one_numeric(client, &me, ERR_BADCHANNAME, name);
955 michael 3912 continue;
956     }
957    
958 michael 9250 if (!HasFlag(client, FLAGS_EXEMPTRESV) &&
959     !(HasUMode(client, UMODE_OPER) && HasOFlag(client, OPER_FLAG_JOIN_RESV)) &&
960     ((resv = resv_find(name, match)) && resv_exempt_find(client, resv) == false))
961 michael 3912 {
962 michael 9250 sendto_one_numeric(client, &me, ERR_CHANBANREASON, name, resv->reason);
963 michael 4151 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
964 michael 3912 "Forbidding reserved channel %s from user %s",
965 michael 9250 name, client_get_name(client, HIDE_IP));
966 michael 3912 continue;
967     }
968    
969 michael 9250 if (dlink_list_length(&client->channel) >=
970 michael 3933 ((class->max_channels) ? class->max_channels : ConfigChannel.max_channels))
971 michael 3912 {
972 michael 9250 sendto_one_numeric(client, &me, ERR_TOOMANYCHANNELS, name);
973 michael 3912 break;
974     }
975    
976 michael 9200 struct Channel *channel = hash_find_channel(name);
977     if (channel)
978 michael 3912 {
979 michael 9455 if (member_find_link(client, channel))
980 michael 3912 continue;
981    
982 michael 7557 /* can_join() checks for +i, +l, key, bans, etc. */
983 michael 9250 int ret = can_join(client, channel, key);
984 michael 7557 if (ret)
985 michael 3912 {
986 michael 9250 sendto_one_numeric(client, &me, ret, channel->name);
987 michael 3912 continue;
988     }
989    
990     /*
991     * This should never be the case unless there is some sort of
992 michael 9250 * persistent channels.
993 michael 3912 */
994 michael 9081 if (dlink_list_length(&channel->members) == 0)
995 michael 3912 flags = CHFL_CHANOP;
996     else
997     flags = 0;
998     }
999     else
1000     {
1001     flags = CHFL_CHANOP;
1002 michael 9081 channel = channel_make(name);
1003 michael 3912 }
1004    
1005 michael 9250 if (!HasUMode(client, UMODE_OPER))
1006     check_spambot_warning(client, channel->name);
1007 michael 3912
1008 michael 9250 add_user_to_channel(channel, client, flags, true);
1009 michael 3912
1010     /*
1011 michael 5545 * Set timestamp if appropriate, and propagate
1012 michael 3912 */
1013     if (flags == CHFL_CHANOP)
1014     {
1015 michael 9081 channel->creation_time = event_base->time.sec_real;
1016     AddCMode(channel, MODE_TOPICLIMIT);
1017     AddCMode(channel, MODE_NOPRIVMSGS);
1018 michael 3912
1019 michael 8513 sendto_server(NULL, 0, 0, ":%s SJOIN %ju %s +nt :@%s",
1020 michael 9081 me.id, channel->creation_time,
1021 michael 9250 channel->name, client->id);
1022 michael 3912
1023     /*
1024     * Notify all other users on the new channel
1025     */
1026 michael 9081 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
1027 michael 9250 client->name, client->username,
1028     client->host, channel->name, client->account, client->info);
1029 michael 9081 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
1030 michael 9250 client->name, client->username,
1031     client->host, channel->name);
1032 michael 9081 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s MODE %s +nt",
1033     me.name, channel->name);
1034 michael 3912 }
1035     else
1036     {
1037 michael 8513 sendto_server(NULL, 0, 0, ":%s JOIN %ju %s +",
1038 michael 9250 client->id, channel->creation_time,
1039 michael 9081 channel->name);
1040 michael 3912
1041 michael 9081 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
1042 michael 9250 client->name, client->username,
1043     client->host, channel->name, client->account, client->info);
1044 michael 9081 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
1045 michael 9250 client->name, client->username,
1046     client->host, channel->name);
1047 michael 3912 }
1048    
1049 michael 9250 if (client->away[0])
1050     sendto_channel_local(client, channel, 0, CAP_AWAY_NOTIFY, 0,
1051 michael 8542 ":%s!%s@%s AWAY :%s",
1052 michael 9250 client->name, client->username,
1053     client->host, client->away);
1054 michael 8542
1055 michael 9265 struct Invite *invite = invite_find(channel, client);
1056 michael 9200 if (invite)
1057 michael 9265 invite_del(invite);
1058 michael 3912
1059 michael 9081 if (channel->topic[0])
1060 michael 3912 {
1061 michael 9250 sendto_one_numeric(client, &me, RPL_TOPIC, channel->name, channel->topic);
1062     sendto_one_numeric(client, &me, RPL_TOPICWHOTIME, channel->name,
1063 michael 9081 channel->topic_info, channel->topic_time);
1064 michael 3912 }
1065    
1066 michael 9476 channel_send_namereply(client, channel);
1067 michael 3912
1068 michael 9250 client->connection->last_join_time = event_base->time.sec_monotonic;
1069 michael 3912 }
1070     }
1071    
1072     /*! \brief Removes a client from a specific channel
1073 michael 9250 * \param client Pointer to client to remove
1074     * \param name Name of channel to remove from
1075     * \param reason Part reason to show
1076 michael 3912 */
1077     static void
1078 michael 9250 channel_part_one_client(struct Client *client, const char *name, const char *reason)
1079 michael 3912 {
1080 michael 9365 struct Channel *channel = hash_find_channel(name);
1081     if (channel == NULL)
1082 michael 3912 {
1083 michael 9250 sendto_one_numeric(client, &me, ERR_NOSUCHCHANNEL, name);
1084 michael 3912 return;
1085     }
1086    
1087 michael 9455 struct ChannelMember *member = member_find_link(client, channel);
1088 michael 9365 if (member == NULL)
1089 michael 3912 {
1090 michael 9250 sendto_one_numeric(client, &me, ERR_NOTONCHANNEL, channel->name);
1091 michael 3912 return;
1092     }
1093    
1094 michael 9250 if (MyConnect(client) && !HasUMode(client, UMODE_OPER))
1095     check_spambot_warning(client, NULL);
1096 michael 3912
1097     /*
1098 michael 9365 * Remove user from the old channel (if any). Only allow /part reasons in -m chans.
1099 michael 3912 */
1100 michael 9250 if (*reason && (!MyConnect(client) ||
1101     ((client->connection->created_monotonic +
1102 michael 8919 ConfigGeneral.anti_spam_exit_message_time) < event_base->time.sec_monotonic &&
1103 michael 9250 can_send(channel, client, member, reason, false) < 0)))
1104 michael 3912 {
1105 michael 9250 sendto_server(client, 0, 0, ":%s PART %s :%s",
1106     client->id, channel->name, reason);
1107 michael 9081 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s!%s@%s PART %s :%s",
1108 michael 9250 client->name, client->username,
1109     client->host, channel->name, reason);
1110 michael 3912 }
1111     else
1112     {
1113 michael 9250 sendto_server(client, 0, 0, ":%s PART %s",
1114     client->id, channel->name);
1115 michael 9081 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s!%s@%s PART %s",
1116 michael 9250 client->name, client->username,
1117     client->host, channel->name);
1118 michael 3912 }
1119    
1120 michael 4815 remove_user_from_channel(member);
1121 michael 3912 }
1122    
1123     void
1124 michael 9250 channel_do_part(struct Client *client, char *channel, const char *reason)
1125 michael 3912 {
1126 michael 7797 char *p = NULL;
1127 michael 4785 char buf[KICKLEN + 1] = "";
1128 michael 3912
1129 michael 9250 assert(IsClient(client));
1130 michael 5590
1131 michael 3937 if (!EmptyString(reason))
1132 michael 4785 strlcpy(buf, reason, sizeof(buf));
1133 michael 3912
1134 michael 7797 for (const char *name = strtok_r(channel, ",", &p); name;
1135     name = strtok_r(NULL, ",", &p))
1136 michael 9250 channel_part_one_client(client, name, buf);
1137 michael 3912 }

Properties

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