This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Undernet IRC Server Source Code.".

The branch, antiflood has been created
        at  8864617996e0bd38a44067073b36e0382aedacc2 (commit)

- Log -----------------------------------------------------------------
commit 8864617996e0bd38a44067073b36e0382aedacc2
Author: Michael Poole <[email protected]>
Date:   Wed Jan 25 22:25:38 2012 -0500

    Minor cleanups for the channel anti-flood changes.
    
    include/channel.h (STATUS_FLOOD_NOTICED): Move closer to its macros.
      (SetFloodNoticed): Fix typo.
      (NOTICE): Delete this.
      (flood_attack_channel): Update name of the first parameter.
    
    ircd/channel.c (client_can_send_to_channel): Flatten a nested if.
      (flood_attack_channel): Update parameter name.
    
    ircd/ircd_relay.c (relay_channel_message): Remove dead store to perm.
      (relay_channel_message): Likewise.

diff --git a/include/channel.h b/include/channel.h
index 4c4c663..c35a4cd 100644
--- a/include/channel.h
+++ b/include/channel.h
@@ -146,8 +146,6 @@ typedef enum ChannelGetType {
 #define MODE_ADD       0x40000000
 #define MODE_DEL       0x20000000
 
-#define STATUS_FLOOD_NOTICED 0x10000000 /* XXX is this really free ? */
-
 /* used in ListingArgs.flags */
 
 #define LISTARG_TOPICLIMITS     0x0001
@@ -234,15 +232,12 @@ struct Membership {
 #define ClearBurstJoined(x) ((x)->status &= ~CHFL_BURST_JOINED)
 #define ClearDelayedJoin(x) ((x)->status &= ~CHFL_DELAYED)
 
-/* Channel flood control -Dianora */
-/* Sort later if needed */
+/* Channel flood control */
+#define STATUS_FLOOD_NOTICED 0x10000000
 #define IsSetFloodNoticed(x) ((x)->status & STATUS_FLOOD_NOTICED)
-#define SetFloodNoticed(x)   ((x)->status != STATUS_FLOOD_NOTICED)
+#define SetFloodNoticed(x)   ((x)->status |= STATUS_FLOOD_NOTICED)
 #define ClearFloodNoticed(x) ((x)->status &= ~STATUS_FLOOD_NOTICED)
 
-/* XXX NOTICE might not belong in channel.h ;-) */
-#define NOTICE 1
-
 /** Mode information for a channel */
 struct Mode {
   unsigned int mode;
@@ -285,7 +280,7 @@ struct Channel {
   struct SLink*      invites;     /**< List of invites on this channel */
   struct Ban*        banlist;      /**< List of bans on this channel */
   struct Mode        mode;        /**< This channels mode */
-  int               status;
+  int               status;       /**< Anti-flood status */
   char               topic[TOPICLEN + 1]; /**< Channels topic */
   char               topic_nick[NICKLEN + 1]; /**< Nick of the person who set
                                                *  The topic
@@ -464,6 +459,6 @@ extern struct Ban *find_ban(struct Client *cptr, struct Ban 
*banlist);
 extern int apply_ban(struct Ban **banlist, struct Ban *newban, int free);
 extern void free_ban(struct Ban *ban);
 
-int flood_attack_channel(int p_or_n, struct Client *source_p,
+int flood_attack_channel(int is_notice, struct Client *source_p,
                      struct Channel *chptr);
 #endif /* INCLUDED_channel_h */
diff --git a/ircd/channel.c b/ircd/channel.c
index ca44469..31bfa29 100644
--- a/ircd/channel.c
+++ b/ircd/channel.c
@@ -763,12 +763,10 @@ int client_can_send_to_channel(struct Client *cptr, 
struct Channel *chptr, int r
     if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) ||
        ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(cptr)))
       return 0;
-    else {
-      if (find_ban(cptr, chptr->banlist))
-       return 0;
-      else 
-       return CHFL_CAN_SEND;
-    }
+    else if (find_ban(cptr, chptr->banlist))
+      return 0;
+    else
+      return CHFL_CAN_SEND;
   }
   return member_can_send_to_channel(member, reveal);
 }
@@ -3663,12 +3661,13 @@ void RevealDelayedJoinIfNeeded(struct Client *sptr, 
struct Channel *chptr)
  * Side effects: check for flood attack on target chptr
  * modified from Hybrid by Dianora
  *
- * @param[in] flag 0 if PRIVMSG 1 if NOTICE. RFC says NOTICE must not auto 
reply
- * @param[in] source_p source Client 
+ * @param[in] is_notice 0 if PRIVMSG, 1 if NOTICE (RFC says NOTICE
+ *   must not auto reply)
+ * @param[in] source_p source Client
  * @param[in] pointer to target channel
  * @param[out] 1 if target is under flood attack
  */
-int flood_attack_channel(int p_or_n, struct Client *source_p,
+int flood_attack_channel(int is_notice, struct Client *source_p,
                      struct Channel *chptr)
 {
   int delta;
@@ -3701,7 +3700,7 @@ int flood_attack_channel(int p_or_n, struct Client 
*source_p,
         /* Add a bit of penalty */
         chptr->received_number_of_privmsgs += 2;
       }
-      if (MyUser(source_p) && (p_or_n != NOTICE))
+      if (MyUser(source_p) && !is_notice)
         sendcmdto_one(&me, CMD_NOTICE, source_p,
          "%s :*** Message to %s throttled due to flooding", cli_name(source_p),
                chptr->chname);
diff --git a/ircd/ircd_relay.c b/ircd/ircd_relay.c
index 1da202c..07d4a7a 100644
--- a/ircd/ircd_relay.c
+++ b/ircd/ircd_relay.c
@@ -86,7 +86,8 @@
 void relay_channel_message(struct Client* sptr, const char* name, const char* 
text)
 {
   struct Channel* chptr;
-  int perm=0;
+  int perm;
+
   assert(0 != sptr);
   assert(0 != name);
   assert(0 != text);
@@ -126,7 +127,8 @@ void relay_channel_message(struct Client* sptr, const char* 
name, const char* te
 void relay_channel_notice(struct Client* sptr, const char* name, const char* 
text)
 {
   struct Channel* chptr;
-  int perm=0;
+  int perm;
+
   assert(0 != sptr);
   assert(0 != name);
   assert(0 != text);
commit b714bd2b740b13c11a1dd0c96afe84ccb24cf740
Author: Michael Poole <[email protected]>
Date:   Wed Jan 25 22:24:17 2012 -0500

    - First pass at adding anti channel flood code to ircu
    
    [Code by Diane Bruce <[email protected]>.  Conflicts resolved, with one tweak,
    by Entrope: Reorder the test in ircd_relay.c to change less code.  The
    old change conflicted with delayed join handling.]
    
    Conflicts:
    
        include/ircd_features.h
        ircd/channel.c
        ircd/ircd_features.c
        ircd/ircd_relay.c

diff --git a/include/channel.h b/include/channel.h
index 7cafdf8..4c4c663 100644
--- a/include/channel.h
+++ b/include/channel.h
@@ -146,6 +146,8 @@ typedef enum ChannelGetType {
 #define MODE_ADD       0x40000000
 #define MODE_DEL       0x20000000
 
+#define STATUS_FLOOD_NOTICED 0x10000000 /* XXX is this really free ? */
+
 /* used in ListingArgs.flags */
 
 #define LISTARG_TOPICLIMITS     0x0001
@@ -232,6 +234,15 @@ struct Membership {
 #define ClearBurstJoined(x) ((x)->status &= ~CHFL_BURST_JOINED)
 #define ClearDelayedJoin(x) ((x)->status &= ~CHFL_DELAYED)
 
+/* Channel flood control -Dianora */
+/* Sort later if needed */
+#define IsSetFloodNoticed(x) ((x)->status & STATUS_FLOOD_NOTICED)
+#define SetFloodNoticed(x)   ((x)->status != STATUS_FLOOD_NOTICED)
+#define ClearFloodNoticed(x) ((x)->status &= ~STATUS_FLOOD_NOTICED)
+
+/* XXX NOTICE might not belong in channel.h ;-) */
+#define NOTICE 1
+
 /** Mode information for a channel */
 struct Mode {
   unsigned int mode;
@@ -274,10 +285,13 @@ struct Channel {
   struct SLink*      invites;     /**< List of invites on this channel */
   struct Ban*        banlist;      /**< List of bans on this channel */
   struct Mode        mode;        /**< This channels mode */
+  int               status;
   char               topic[TOPICLEN + 1]; /**< Channels topic */
   char               topic_nick[NICKLEN + 1]; /**< Nick of the person who set
                                                *  The topic
                                                */
+  time_t first_received_message_time; /**< channel flood control */
+  int    received_number_of_privmsgs; /**< number of possible flooding 
messages */
   char               chname[1];           /**< Dynamically allocated string of 
the 
                                     * channel name
                                     */
@@ -450,4 +464,6 @@ extern struct Ban *find_ban(struct Client *cptr, struct Ban 
*banlist);
 extern int apply_ban(struct Ban **banlist, struct Ban *newban, int free);
 extern void free_ban(struct Ban *ban);
 
+int flood_attack_channel(int p_or_n, struct Client *source_p,
+                     struct Channel *chptr);
 #endif /* INCLUDED_channel_h */
diff --git a/include/ircd_features.h b/include/ircd_features.h
index 42c54ac..a9a2e33 100644
--- a/include/ircd_features.h
+++ b/include/ircd_features.h
@@ -156,6 +156,7 @@ enum Feature {
   FEAT_NETWORK,
   FEAT_URL_CLIENTS,
   FEAT_URLREG,
+  FEAT_CHANNEL_FLOOD_COUNT,
 
   FEAT_LAST_F
 };
diff --git a/ircd/channel.c b/ircd/channel.c
index 9c0f192..ca44469 100644
--- a/ircd/channel.c
+++ b/ircd/channel.c
@@ -623,7 +623,7 @@ int is_chan_op(struct Client *cptr, struct Channel *chptr)
  * @param chptr                The channel to check.
  *
  * @returns True if the client (cptr) is a zombie on the channel (chptr),
- *         False otherwise.
+ *         False otherwise.
  *
  * @see \ref zombie
  */
@@ -640,7 +640,7 @@ int is_zombie(struct Client *cptr, struct Channel *chptr)
 
 /** Returns if a user has voice on a channel.
  *
- * @param cptr         The client
+ * @param cptr The client
  * @param chptr        The channel
  *
  * @returns True if the client (cptr) is voiced on (chptr) and is not a zombie.
@@ -657,6 +657,9 @@ int has_voice(struct Client* cptr, struct Channel* chptr)
   return 0;
 }
 
+/* XXX Maybe move this into channel.h ? - Dianora */
+#define CHFL_CAN_SEND  0x800000
+
 /** Can this member send to a channel
  *
  * A user can speak on a channel iff:
@@ -673,9 +676,11 @@ int has_voice(struct Client* cptr, struct Channel* chptr)
  *
  * @param member       The membership of the user
  * @param reveal       If true, the user will be "revealed" on a delayed
- *                     joined channel.
+ *                     joined channel.
  *
- * @returns True if the client can speak on the channel.
+ * @returns CHFL_CAN_SEND or CHFL_VOICED_OR_OPPED if
+ *         the client can speak on the channel.
+ *         0 if the client cannot speak on the channel.
  */
 int member_can_send_to_channel(struct Membership* member, int reveal)
 {
@@ -689,7 +694,7 @@ int member_can_send_to_channel(struct Membership* member, 
int reveal)
   {
     if (IsDelayedJoin(member) && reveal)
       RevealDelayedJoin(member);
-    return 1;
+    return CHFL_CAN_SEND;
   }
 
   /* Discourage using the Apass to get op.  They should use the Upass. */
@@ -698,7 +703,7 @@ int member_can_send_to_channel(struct Membership* member, 
int reveal)
 
   /* If you have voice or ops, you can speak. */
   if (IsVoicedOrOpped(member))
-    return 1;
+    return CHFL_VOICED_OR_OPPED;
 
   /*
    * If it's moderated, and you aren't a privileged user, you can't
@@ -718,9 +723,10 @@ int member_can_send_to_channel(struct Membership* member, 
int reveal)
   if (IsDelayedJoin(member) && reveal)
     RevealDelayedJoin(member);
 
-  return 1;
+  return CHFL_CAN_SEND;
 }
 
+
 /** Check if a client can send to a channel.
  *
  * Has the added check over member_can_send_to_channel() of servers can
@@ -731,11 +737,12 @@ int member_can_send_to_channel(struct Membership* member, 
int reveal)
  * @param reveal If the user should be revealed (see 
  *             member_can_send_to_channel())
  *
- * @returns true if the client is allowed to speak on the channel, false 
- *             otherwise
+ * @returns CHFL_CAN_SEND
+ *         if the client is allowed to speak on the channel, 0 otherwise
  *
  * @see member_can_send_to_channel()
  */
+
 int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr, int 
reveal)
 {
   struct Membership *member;
@@ -744,7 +751,7 @@ int client_can_send_to_channel(struct Client *cptr, struct 
Channel *chptr, int r
    * Servers can always speak on channels.
    */
   if (IsServer(cptr))
-    return 1;
+    return CHFL_CAN_SEND;
 
   member = find_channel_member(cptr, chptr);
 
@@ -756,8 +763,12 @@ int client_can_send_to_channel(struct Client *cptr, struct 
Channel *chptr, int r
     if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) ||
        ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(cptr)))
       return 0;
-    else
-      return !find_ban(cptr, chptr->banlist);
+    else {
+      if (find_ban(cptr, chptr->banlist))
+       return 0;
+      else 
+       return CHFL_CAN_SEND;
+    }
   }
   return member_can_send_to_channel(member, reveal);
 }
@@ -3647,3 +3658,58 @@ void RevealDelayedJoinIfNeeded(struct Client *sptr, 
struct Channel *chptr)
   if (member && IsDelayedJoin(member))
     RevealDelayedJoin(member);
 }
+
+/** Check whether a channel is being flooded or not
+ * Side effects: check for flood attack on target chptr
+ * modified from Hybrid by Dianora
+ *
+ * @param[in] flag 0 if PRIVMSG 1 if NOTICE. RFC says NOTICE must not auto 
reply
+ * @param[in] source_p source Client 
+ * @param[in] pointer to target channel
+ * @param[out] 1 if target is under flood attack
+ */
+int flood_attack_channel(int p_or_n, struct Client *source_p,
+                     struct Channel *chptr)
+{
+  int delta;
+
+  if (feature_int(FEAT_CHANNEL_FLOOD_COUNT) != 0)
+  {
+    if ((chptr->first_received_message_time + 1) < CurrentTime)
+    {
+      delta = CurrentTime - chptr->first_received_message_time;
+      chptr->received_number_of_privmsgs -= delta;
+      chptr->first_received_message_time = CurrentTime;
+      if (chptr->received_number_of_privmsgs <= 0)
+      {
+        chptr->received_number_of_privmsgs = 0;
+        ClearFloodNoticed(chptr);
+      }
+    }
+
+    if ((chptr->received_number_of_privmsgs >=
+           feature_int(FEAT_CHANNEL_FLOOD_COUNT))
+               || IsSetFloodNoticed(chptr))
+    {
+      if (!IsSetFloodNoticed(chptr))
+      {
+        sendto_opmask_butone(0, SNO_OLDSNO,
+                             "Possible Flooder %s target: %s",
+                             cli_name(source_p), chptr->chname);
+        SetFloodNoticed(chptr);
+
+        /* Add a bit of penalty */
+        chptr->received_number_of_privmsgs += 2;
+      }
+      if (MyUser(source_p) && (p_or_n != NOTICE))
+        sendcmdto_one(&me, CMD_NOTICE, source_p,
+         "%s :*** Message to %s throttled due to flooding", cli_name(source_p),
+               chptr->chname);
+      return(1);
+    }
+    else
+      chptr->received_number_of_privmsgs++;
+  }
+
+  return(0);
+}
diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c
index 6d64f89..715d11c 100644
--- a/ircd/ircd_features.c
+++ b/ircd/ircd_features.c
@@ -421,6 +421,7 @@ static struct FeatureDesc {
   F_S(NETWORK, 0, "UnderNet", 0),
   F_S(URL_CLIENTS, 0, "ftp://ftp.undernet.org/pub/irc/clients";, 0),
   F_S(URLREG, 0, "http://cservice.undernet.org/live/";, 0),
+  F_I(CHANNEL_FLOOD_COUNT, 0, 3, 0),
 
 #undef F_S
 #undef F_B
diff --git a/ircd/ircd_relay.c b/ircd/ircd_relay.c
index b7a751d..1da202c 100644
--- a/ircd/ircd_relay.c
+++ b/ircd/ircd_relay.c
@@ -86,6 +86,7 @@
 void relay_channel_message(struct Client* sptr, const char* name, const char* 
text)
 {
   struct Channel* chptr;
+  int perm=0;
   assert(0 != sptr);
   assert(0 != name);
   assert(0 != text);
@@ -97,7 +98,9 @@ void relay_channel_message(struct Client* sptr, const char* 
name, const char* te
   /*
    * This first: Almost never a server/service
    */
-  if (!client_can_send_to_channel(sptr, chptr, 0)) {
+  perm = client_can_send_to_channel(sptr, chptr, 1);
+
+  if (perm == 0) {
     send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
     return;
   }
@@ -105,6 +108,10 @@ void relay_channel_message(struct Client* sptr, const 
char* name, const char* te
       check_target_limit(sptr, chptr, chptr->chname, 0))
     return;
 
+  /* Chanops and Voiced get a free pass */
+  if (((perm & CHFL_VOICED_OR_OPPED) == 0)
+      && flood_attack_channel(0, sptr, chptr))
+    return;
   RevealDelayedJoinIfNeeded(sptr, chptr);
   sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
                           SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
@@ -119,6 +126,7 @@ void relay_channel_message(struct Client* sptr, const char* 
name, const char* te
 void relay_channel_notice(struct Client* sptr, const char* name, const char* 
text)
 {
   struct Channel* chptr;
+  int perm=0;
   assert(0 != sptr);
   assert(0 != name);
   assert(0 != text);
@@ -128,13 +136,19 @@ void relay_channel_notice(struct Client* sptr, const 
char* name, const char* tex
   /*
    * This first: Almost never a server/service
    */
-  if (!client_can_send_to_channel(sptr, chptr, 0))
+  perm = client_can_send_to_channel(sptr, chptr, 1);
+
+  if (perm == 0)
     return;
 
   if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
       check_target_limit(sptr, chptr, chptr->chname, 0))
     return;
 
+  /* Chanops and Voiced get a free pass */
+  if (((perm & CHFL_VOICED_OR_OPPED) == 0)
+      && flood_attack_channel(1, sptr, chptr))
+    return;
   RevealDelayedJoinIfNeeded(sptr, chptr);
   sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
                           SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
-----------------------------------------------------------------------


hooks/post-receive
-- 
Undernet IRC Server Source Code.
_______________________________________________
Patches mailing list
[email protected]
http://undernet.sbg.org/mailman/listinfo/patches

Reply via email to