ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/channel.c (file contents):
Revision 1592 by michael, Sat Oct 27 21:02:32 2012 UTC vs.
Revision 1954 by michael, Mon May 6 18:51:19 2013 UTC

# Line 30 | Line 30
30   #include "channel_mode.h"
31   #include "client.h"
32   #include "hash.h"
33 + #include "conf.h"
34   #include "hostmask.h"
35   #include "irc_string.h"
35 #include "sprintf_irc.h"
36   #include "ircd.h"
37   #include "numeric.h"
38   #include "s_serv.h"             /* captab */
39   #include "s_user.h"
40   #include "send.h"
41 #include "conf.h"             /* ConfigFileEntry, ConfigChannel */
41   #include "event.h"
42   #include "memory.h"
43 < #include "balloc.h"
43 > #include "mempool.h"
44 > #include "s_misc.h"
45 > #include "resv.h"
46  
47   struct config_channel_entry ConfigChannel;
48   dlink_list global_channel_list = { NULL, NULL, 0 };
49 < BlockHeap *ban_heap;    /*! \todo ban_heap shouldn't be a global var */
49 > mp_pool_t *ban_pool;    /*! \todo ban_pool shouldn't be a global var */
50  
51 < static BlockHeap *member_heap = NULL;
52 < static BlockHeap *channel_heap = NULL;
51 > static mp_pool_t *member_pool = NULL;
52 > static mp_pool_t *channel_pool = NULL;
53  
54   static char buf[IRCD_BUFSIZE];
55   static char modebuf[MODEBUFLEN];
# Line 58 | Line 59 | static char parabuf[MODEBUFLEN];
59   /*! \brief Initializes the channel blockheap, adds known channel CAPAB
60   */
61   void
62 < init_channels(void)
62 > channel_init(void)
63   {
64    add_capability("EX", CAP_EX, 1);
65    add_capability("IE", CAP_IE, 1);
66    add_capability("CHW", CAP_CHW, 1);
67  
68 <  channel_heap = BlockHeapCreate("channel", sizeof(struct Channel), CHANNEL_HEAP_SIZE);
69 <  ban_heap = BlockHeapCreate("ban", sizeof(struct Ban), BAN_HEAP_SIZE);
70 <  member_heap = BlockHeapCreate("member", sizeof(struct Membership), CHANNEL_HEAP_SIZE*2);
68 >  channel_pool = mp_pool_new(sizeof(struct Channel), MP_CHUNK_SIZE_CHANNEL);
69 >  ban_pool = mp_pool_new(sizeof(struct Ban), MP_CHUNK_SIZE_BAN);
70 >  member_pool = mp_pool_new(sizeof(struct Membership), MP_CHUNK_SIZE_MEMBER);
71   }
72  
73   /*! \brief adds a user to a channel by adding another link to the
# Line 103 | Line 104 | add_user_to_channel(struct Channel *chpt
104        if (!IsSetJoinFloodNoticed(chptr))
105        {
106          SetJoinFloodNoticed(chptr);
107 <        sendto_realops_flags(UMODE_BOTS, L_ALL,
107 >        sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
108                               "Possible Join Flooder %s on %s target: %s",
109                               get_client_name(who, HIDE_IP),
110                               who->servptr->name, chptr->chname);
# Line 113 | Line 114 | add_user_to_channel(struct Channel *chpt
114      chptr->last_join_time = CurrentTime;
115    }
116  
117 <  ms = BlockHeapAlloc(member_heap);
117 >  ms = mp_pool_get(member_pool);
118 >  memset(ms, 0, sizeof(*ms));
119 >
120    ms->client_p = who;
121    ms->chptr = chptr;
122    ms->flags = flags;
# Line 135 | Line 138 | remove_user_from_channel(struct Membersh
138    dlinkDelete(&member->channode, &chptr->members);
139    dlinkDelete(&member->usernode, &client_p->channel);
140  
141 <  BlockHeapFree(member_heap, member);
141 >  mp_pool_release(member);
142  
143    if (chptr->members.head == NULL)
144      destroy_channel(chptr);
# Line 151 | Line 154 | static void
154   send_members(struct Client *client_p, struct Channel *chptr,
155               char *lmodebuf, char *lparabuf)
156   {
157 <  struct Membership *ms;
155 <  dlink_node *ptr;
157 >  const dlink_node *ptr = NULL;
158    int tlen;              /* length of text to append */
159    char *t, *start;       /* temp char pointer */
160  
161 <  start = t = buf + ircsprintf(buf, ":%s SJOIN %lu %s %s %s:",
162 <                               ID_or_name(&me, client_p),
163 <                               (unsigned long)chptr->channelts,
164 <                               chptr->chname, lmodebuf, lparabuf);
161 >  start = t = buf + snprintf(buf, sizeof(buf), ":%s SJOIN %lu %s %s %s:",
162 >                             ID_or_name(&me, client_p),
163 >                             (unsigned long)chptr->channelts,
164 >                             chptr->chname, lmodebuf, lparabuf);
165  
166    DLINK_FOREACH(ptr, chptr->members.head)
167    {
168 <    ms = ptr->data;
168 >    const struct Membership *ms = ptr->data;
169  
170      tlen = strlen(IsCapable(client_p, CAP_TS6) ?
171        ID(ms->client_p) : ms->client_p->name) + 1;  /* nick + space */
# Line 216 | Line 218 | send_members(struct Client *client_p, st
218   */
219   static void
220   send_mode_list(struct Client *client_p, struct Channel *chptr,
221 <               dlink_list *top, char flag)
221 >               const dlink_list *top, char flag)
222   {
223    int ts5 = !IsCapable(client_p, CAP_TS6);
224 <  dlink_node *lp;
223 <  struct Ban *banptr;
224 >  const dlink_node *lp = NULL;
225    char pbuf[IRCD_BUFSIZE];
226    int tlen, mlen, cur_len, count = 0;
227    char *mp = NULL, *pp = pbuf;
# Line 229 | Line 230 | send_mode_list(struct Client *client_p,
230      return;
231  
232    if (ts5)
233 <    mlen = ircsprintf(buf, ":%s MODE %s +", me.name, chptr->chname);
233 >    mlen = snprintf(buf, sizeof(buf), ":%s MODE %s +", me.name, chptr->chname);
234    else
235 <    mlen = ircsprintf(buf, ":%s BMASK %lu %s %c :", me.id,
236 <                      (unsigned long)chptr->channelts, chptr->chname, flag);
235 >    mlen = snprintf(buf, sizeof(buf), ":%s BMASK %lu %s %c :", me.id,
236 >                   (unsigned long)chptr->channelts, chptr->chname, flag);
237  
238    /* MODE needs additional one byte for space between buf and pbuf */
239    cur_len = mlen + ts5;
# Line 240 | Line 241 | send_mode_list(struct Client *client_p,
241  
242    DLINK_FOREACH(lp, top->head)
243    {
244 <    banptr = lp->data;
244 >    const struct Ban *banptr = lp->data;
245  
246      /* must add another b/e/I letter if we use MODE */
247      tlen = banptr->len + 3 + ts5;
# Line 270 | Line 271 | send_mode_list(struct Client *client_p,
271        *mp = '\0';
272      }
273  
274 <    pp += ircsprintf(pp, "%s!%s@%s ", banptr->name, banptr->username,
275 <                     banptr->host);
274 >    pp += sprintf(pp, "%s!%s@%s ", banptr->name, banptr->username,
275 >                  banptr->host);
276      cur_len += tlen;
277    }
278  
# Line 291 | Line 292 | send_channel_modes(struct Client *client
292    send_members(client_p, chptr, modebuf, parabuf);
293  
294    send_mode_list(client_p, chptr, &chptr->banlist, 'b');
295 <
296 <  if (IsCapable(client_p, CAP_EX))
296 <    send_mode_list(client_p, chptr, &chptr->exceptlist, 'e');
297 <  if (IsCapable(client_p, CAP_IE))
298 <    send_mode_list(client_p, chptr, &chptr->invexlist, 'I');
295 >  send_mode_list(client_p, chptr, &chptr->exceptlist, 'e');
296 >  send_mode_list(client_p, chptr, &chptr->invexlist, 'I');
297   }
298  
299   /*! \brief check channel name for invalid characters
# Line 304 | Line 302 | send_channel_modes(struct Client *client
302   * \return 0 if invalid, 1 otherwise
303   */
304   int
305 < check_channel_name(const char *name, int local)
305 > check_channel_name(const char *name, const int local)
306   {
307    const char *p = name;
308    const int max_length = local ? LOCAL_CHANNELLEN : CHANNELLEN;
# Line 339 | Line 337 | remove_ban(struct Ban *bptr, dlink_list
337    MyFree(bptr->host);
338    MyFree(bptr->who);
339  
340 <  BlockHeapFree(ban_heap, bptr);
340 >  mp_pool_release(bptr);
341   }
342  
343   /* free_channel_list()
# Line 371 | Line 369 | make_channel(const char *chname)
369  
370    assert(!EmptyString(chname));
371  
372 <  chptr = BlockHeapAlloc(channel_heap);
372 >  chptr = mp_pool_get(channel_pool);
373 >
374 >  memset(chptr, 0, sizeof(*chptr));
375  
376    /* doesn't hurt to set it here */
377    chptr->channelts = CurrentTime;
# Line 404 | Line 404 | destroy_channel(struct Channel *chptr)
404    dlinkDelete(&chptr->node, &global_channel_list);
405    hash_del_channel(chptr);
406  
407 <  BlockHeapFree(channel_heap, chptr);
407 >  mp_pool_release(chptr);
408   }
409  
410   /*!
# Line 431 | Line 431 | void
431   channel_member_names(struct Client *source_p, struct Channel *chptr,
432                       int show_eon)
433   {
434 <  struct Client *target_p = NULL;
435 <  struct Membership *ms = NULL;
436 <  dlink_node *ptr = NULL;
434 >  const dlink_node *ptr = NULL;
435    char lbuf[IRCD_BUFSIZE + 1];
436    char *t = NULL, *start = NULL;
437    int tlen = 0;
# Line 442 | Line 440 | channel_member_names(struct Client *sour
440  
441    if (PubChannel(chptr) || is_member)
442    {
443 <    t = lbuf + ircsprintf(lbuf, form_str(RPL_NAMREPLY),
444 <                          me.name, source_p->name,
445 <                          channel_pub_or_secret(chptr),
448 <                          chptr->chname);
443 >    t = lbuf + snprintf(lbuf, sizeof(lbuf), form_str(RPL_NAMREPLY),
444 >                        me.name, source_p->name,
445 >                        channel_pub_or_secret(chptr), chptr->chname);
446      start = t;
447  
448      DLINK_FOREACH(ptr, chptr->members.head)
449      {
450 <      ms       = ptr->data;
454 <      target_p = ms->client_p;
450 >      const struct Membership *ms = ptr->data;
451  
452 <      if (HasUMode(target_p, UMODE_INVISIBLE) && !is_member)
452 >      if (HasUMode(ms->client_p, UMODE_INVISIBLE) && !is_member)
453          continue;
454  
455 <      tlen = strlen(target_p->name) + 1;  /* nick + space */
455 >      tlen = strlen(ms->client_p->name) + 1;  /* nick + space */
456  
457        if (!multi_prefix)
458        {
# Line 480 | Line 476 | channel_member_names(struct Client *sour
476          t = start;
477        }
478  
479 <      t += ircsprintf(t, "%s%s ", get_member_status(ms, multi_prefix),
480 <                      target_p->name);
479 >      t += sprintf(t, "%s%s ", get_member_status(ms, multi_prefix),
480 >                   ms->client_p->name);
481      }
482  
483      if (tlen != 0)
# Line 551 | Line 547 | const char *
547   get_member_status(const struct Membership *ms, int combine)
548   {
549    static char buffer[4];
550 <  char *p = NULL;
555 <
556 <  if (ms == NULL)
557 <    return "";
558 <  p = buffer;
550 >  char *p = buffer;
551  
552    if (ms->flags & CHFL_CHANOP)
553    {
# Line 595 | Line 587 | find_bmask(const struct Client *who, con
587    {
588      const struct Ban *bp = ptr->data;
589  
590 <    if (match(bp->name, who->name) && match(bp->username, who->username))
590 >    if (!match(bp->name, who->name) && !match(bp->username, who->username))
591      {
592        switch (bp->type)
593        {
594          case HM_HOST:
595 <          if (match(bp->host, who->host) || match(bp->host, who->sockhost))
595 >          if (!match(bp->host, who->host) || !match(bp->host, who->sockhost))
596              return 1;
597            break;
598          case HM_IPV4:
# Line 679 | Line 671 | can_join(struct Client *source_p, struct
671   }
672  
673   int
674 < has_member_flags(struct Membership *ms, unsigned int flags)
674 > has_member_flags(const struct Membership *ms, const unsigned int flags)
675   {
676    if (ms != NULL)
677      return ms->flags & flags;
# Line 701 | Line 693 | find_channel_link(struct Client *client_
693    return NULL;
694   }
695  
696 + /*
697 + * Basically the same functionality as in bahamut
698 + */
699 + static int
700 + msg_has_ctrls(const char *message)
701 + {
702 +  const unsigned char *p = (const unsigned char *)message;
703 +
704 +  for (; *p; ++p)
705 +  {
706 +    if (*p > 31 || *p == 1)
707 +      continue;
708 +
709 +    if (*p == 27)
710 +    {
711 +      if (*(p + 1) == '$' ||
712 +          *(p + 1) == '(')
713 +      {
714 +        ++p;
715 +        continue;
716 +      }
717 +    }
718 +
719 +    return 1;
720 +  }
721 +
722 +  return 0;
723 + }
724 +
725   /*!
726   * \param chptr    pointer to Channel struct
727   * \param source_p pointer to Client struct
# Line 710 | Line 731 | find_channel_link(struct Client *client_
731   *         ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
732   */
733   int
734 < can_send(struct Channel *chptr, struct Client *source_p, struct Membership *ms)
734 > can_send(struct Channel *chptr, struct Client *source_p,
735 >         struct Membership *ms, const char *message)
736   {
737 +  struct MaskItem *conf = NULL;
738 +
739    if (IsServer(source_p) || HasFlag(source_p, FLAGS_SERVICE))
740      return CAN_SEND_OPV;
741  
742    if (MyClient(source_p) && !IsExemptResv(source_p))
743      if (!(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv))
744 <      if (!hash_find_resv(chptr->chname) == ConfigChannel.restrict_channels)
744 >      if ((conf = match_find_resv(chptr->chname)) && !resv_find_exempt(source_p, conf))
745          return ERR_CANNOTSENDTOCHAN;
746  
747 <  if (ms != NULL || (ms = find_channel_link(source_p, chptr)))
748 <  {
747 >  if ((chptr->mode.mode & MODE_NOCTRL) && msg_has_ctrls(message))
748 >    return ERR_NOCTRLSONCHAN;
749 >  if (ms || (ms = find_channel_link(source_p, chptr)))
750      if (ms->flags & (CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
751        return CAN_SEND_OPV;
752 +  if (chptr->mode.mode & MODE_MODERATED)
753 +    return ERR_CANNOTSENDTOCHAN;
754 +  if ((chptr->mode.mode & MODE_MODREG) && !HasUMode(source_p, UMODE_REGISTERED))
755 +    return ERR_NEEDREGGEDNICK;
756  
757 <    /* cache can send if quiet_on_ban and banned */
758 <    if (ConfigChannel.quiet_on_ban && MyClient(source_p))
757 >  /* cache can send if banned */
758 >  if (MyClient(source_p))
759 >  {
760 >    if (ms)
761      {
762        if (ms->flags & CHFL_BAN_SILENCED)
763          return ERR_CANNOTSENDTOCHAN;
# Line 742 | Line 773 | can_send(struct Channel *chptr, struct C
773          ms->flags |= CHFL_BAN_CHECKED;
774        }
775      }
776 +    else if (is_banned(chptr, source_p))
777 +      return ERR_CANNOTSENDTOCHAN;
778    }
746  else if (chptr->mode.mode & MODE_NOPRIVMSGS)
747    return ERR_CANNOTSENDTOCHAN;
748
749  if (chptr->mode.mode & MODE_MODERATED)
750    return ERR_CANNOTSENDTOCHAN;
779  
780    return CAN_SEND_NONOP;
781   }
# Line 777 | Line 805 | check_spambot_warning(struct Client *sou
805      {
806        /* Its already known as a possible spambot */
807        if (name != NULL)
808 <        sendto_realops_flags(UMODE_BOTS, L_ALL,
808 >        sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
809                               "User %s (%s@%s) trying to join %s is a possible spambot",
810                               source_p->name, source_p->username,
811                               source_p->host, name);
812        else
813 <        sendto_realops_flags(UMODE_BOTS, L_ALL,
813 >        sendto_realops_flags(UMODE_BOTS, L_ALL, SEND_NOTICE,
814                               "User %s (%s@%s) is a possible spambot",
815                               source_p->name, source_p->username,
816                               source_p->host);
# Line 833 | Line 861 | check_splitmode(void *unused)
861      {
862        splitmode = 1;
863  
864 <      sendto_realops_flags(UMODE_ALL,L_ALL,
864 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
865                             "Network split, activating splitmode");
866        eventAddIsh("check_splitmode", check_splitmode, NULL, 10);
867      }
# Line 841 | Line 869 | check_splitmode(void *unused)
869      {
870        splitmode = 0;
871  
872 <      sendto_realops_flags(UMODE_ALL, L_ALL,
872 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
873                             "Network rejoined, deactivating splitmode");
874        eventDelete(check_splitmode, NULL);
875      }
# Line 856 | Line 884 | check_splitmode(void *unused)
884   */
885   void
886   set_channel_topic(struct Channel *chptr, const char *topic,
887 <                  const char *topic_info, time_t topicts)
887 >                  const char *topic_info, time_t topicts, int local)
888   {
889 <  strlcpy(chptr->topic, topic, sizeof(chptr->topic));
889 >  if (local)
890 >    strlcpy(chptr->topic, topic, IRCD_MIN(sizeof(chptr->topic), ServerInfo.max_topic_length + 1));
891 >  else
892 >    strlcpy(chptr->topic, topic, sizeof(chptr->topic));
893 >
894    strlcpy(chptr->topic_info, topic_info, sizeof(chptr->topic_info));
895    chptr->topic_time = topicts;
896   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)