Add CIDR ban support.
authorMichael Poole <mdpoole@troilus.org>
Thu, 21 Oct 2004 23:14:50 +0000 (23:14 +0000)
committerMichael Poole <mdpoole@troilus.org>
Thu, 21 Oct 2004 23:14:50 +0000 (23:14 +0000)
git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1255 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/channel.h
ircd/channel.c

index 892744b8a40ee403bb87a0142ccdbd556398e78e..c57ab562bece243afcfe65201c54e3d6d2568686 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2004-10-21  Michael Poole <mdpoole@troilus.org>
+
+       * include/channel.h (Ban): Add fields address, nu_len, addrbits to
+       support netmask-based bans.
+
+       * ircd/channel.c (set_ban_mask): New function to parse a ban as
+       either netmask-based or not.
+       (make_ban): Use set_ban_mask().
+       (make_nick_user_ip): Becomes unused; remove it.
+       (is_banned): Rewrite to match only once against the nick!user part
+       of a ban, and compare addresses if BAN_IPMASK is set.
+       (mode_parse_ban): Use set_ban_mask().
+
 2004-10-21  Michael Poole <mdpoole@troilus.org>
 
        * ircd/s_conf.c (attach_iline): Test resolved host names against
index 11ef0120616dd4257eb183b4a0f9445315b0f9b6..980e2d87b0915e2321f8086bae678acd4c807cdd 100644 (file)
@@ -30,6 +30,9 @@
 #include <sys/types.h>
 #define INCLUDED_sys_types_h
 #endif
+#ifndef INCLUDED_res_h
+#include "res.h"
+#endif
 
 struct SLink;
 struct Client;
@@ -259,8 +262,11 @@ struct Mode {
 /** A single ban for a channel. */
 struct Ban {
   struct Ban* next;   /**< next ban in the channel */
+  struct irc_in_addr address; /**< addres for BAN_IPMASK bans */
   time_t when;        /**< timestamp when ban was added */
-  unsigned int flags; /**< modifier flags for the ban */
+  unsigned short flags; /**< modifier flags for the ban */
+  unsigned char nu_len; /**< length of nick!user part of banstr */
+  unsigned char addrbits; /**< netmask length for BAN_IPMASK bans */
   char *who;          /**< name of client that set the ban */
   char *banstr;       /**< hostmask that the ban matches */
 };
index da795598a29cde7170dcb79080d189e68c867363..534e3174683bfff7eb72c994611e3a45b9de5f4a 100644 (file)
@@ -100,6 +100,26 @@ static int list_length(struct SLink *lp)
 }
 #endif
 
+/** Set the mask for a ban, checking for IP masks.
+ * @param[in,out] ban Ban structure to modify.
+ * @param[in] banstr Mask to ban.
+ */
+static void
+set_ban_mask(struct Ban *ban, const char *banstr)
+{
+  char *sep;
+  MyFree(ban->banstr);
+  if (!banstr)
+    return;
+  DupString(ban->banstr, banstr);
+  sep = strrchr(banstr, '@');
+  if (sep) {
+    ban->nu_len = sep - banstr;
+    if (ipmask_parse(sep + 1, &ban->address, &ban->addrbits))
+      ban->flags |= BAN_IPMASK;
+  }
+}
+
 /** Allocate a new Ban structure.
  * @param[in] banstr Ban mask to use.
  * @return Newly allocated ban.
@@ -115,8 +135,7 @@ make_ban(const char *banstr)
   else if (!(ban = MyMalloc(sizeof(*ban))))
     return NULL;
   memset(ban, 0, sizeof(*ban));
-  if (banstr)
-    DupString(ban->banstr, banstr);
+  set_ban_mask(ban, banstr);
   return ban;
 }
 
@@ -228,7 +247,6 @@ struct Client* find_chasing(struct Client* sptr, const char* user, int* chasing)
  * @param name The ident
  * @param host the hostname
  * @returns namebuf
- * @see make_nick_user_ip()
  */
 static char *make_nick_user_host(char *namebuf, const char *nick,
                                 const char *name, const char *host)
@@ -238,26 +256,6 @@ static char *make_nick_user_host(char *namebuf, const char *nick,
   return namebuf;
 }
 
-/** Create a hostmask using an IP address
- * Create a string of form "foo!bar@123.456.789.123" given foo, bar and the
- * IP-number as the parameters.  If NULL, they become "*".
- *
- * @param ipbuf Buffer at least NICKLEN+USERLEN+SOCKIPLEN+4 to hold the final
- *             match.
- * @param nick The nickname (or NULL for *)
- * @param name The ident (or NULL for *)
- * @param ip   The IP address
- * @returns ipbuf
- * @see make_nick_user_host()
- */
-#define NUI_BUFSIZE    (NICKLEN + USERLEN + SOCKIPLEN + 4)
-static char *make_nick_user_ip(char *ipbuf, char *nick, char *name,
-                              const struct irc_in_addr *ip)
-{
-  ircd_snprintf(0, ipbuf, NUI_BUFSIZE, "%s!%s@%s", nick, name, ircd_ntoa(ip));
-  return ipbuf;
-}
-
 /** Decrement the count of users, and free if empty.
  * Subtract one user from channel i (and free channel * block, if channel 
  * became empty).
@@ -524,13 +522,9 @@ static int is_banned(struct Client *cptr, struct Channel *chptr,
                      struct Membership* member)
 {
   struct Ban*   tmp;
+  char          nu[NICKLEN + USERLEN + 2];
   char          tmphost[HOSTLEN + 1];
-  char          nu_host[NUH_BUFSIZE];
-  char          nu_realhost[NUH_BUFSIZE];
-  char          nu_ip[NUI_BUFSIZE];
-  char*         s;
   char*         sr = NULL;
-  char*         ip_s = NULL;
 
   if (!IsUser(cptr))
     return 0;
@@ -538,37 +532,33 @@ static int is_banned(struct Client *cptr, struct Channel *chptr,
   if (member && IsBanValid(member))
     return IsBanned(member);
 
-  s = make_nick_user_host(nu_host, cli_name(cptr), (cli_user(cptr))->username,
-                         (cli_user(cptr))->host);
+  ircd_snprintf(0, nu, sizeof(nu), "%s!%s",
+                cli_name(cptr), cli_user(cptr)->username);
   if (IsAccount(cptr))
   {
     if (HasHiddenHost(cptr))
     {
-      sr = make_nick_user_host(nu_realhost, cli_name(cptr),
-                               (cli_user(cptr))->username,
-                               cli_user(cptr)->realhost);
+      sr = cli_user(cptr)->realhost;
     }
     else
     {
       ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s",
                     cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
-      sr = make_nick_user_host(nu_realhost, cli_name(cptr),
-                               cli_user(cptr)->username,
-                               tmphost);      
+      sr = tmphost;
     }
   }
 
   for (tmp = chptr->banlist; tmp; tmp = tmp->next) {
-    if ((tmp->flags & BAN_IPMASK)) {
-      if (!ip_s)
-        ip_s = make_nick_user_ip(nu_ip, cli_name(cptr),
-                                (cli_user(cptr))->username, &cli_ip(cptr));
-      if (match(tmp->banstr, ip_s) == 0)
-        break;
-    }
-    if (match(tmp->banstr, s) == 0)
-      break;
-    else if (sr && match(tmp->banstr, sr) == 0)
+    int res;
+    tmp->banstr[tmp->nu_len] = '\0';
+    res = match(tmp->banstr, nu);
+    tmp->banstr[tmp->nu_len] = '@';
+    if (res)
+      continue;
+    if (((tmp->flags & BAN_IPMASK)
+         && ipmask_check(&cli_ip(cptr), &tmp->address, tmp->addrbits))
+        || match(tmp->banstr + tmp->nu_len + 1, cli_user(cptr)->host) == 0
+        || (sr && match(tmp->banstr + tmp->nu_len + 1, sr) == 0))
       break;
   }
 
@@ -2865,15 +2855,10 @@ mode_parse_ban(struct ParseState *state, int *flag_p)
   if (state->dir == MODE_ADD) {
     newban = state->banlist + (state->numbans++);
     newban->next = 0;
-
-    DupString(newban->banstr, t_str);
+    newban->flags = BAN_ADD;
+    set_ban_mask(newban, t_str);
     newban->who = cli_name(state->sptr);
     newban->when = TStime();
-
-    newban->flags = BAN_ADD;
-
-    if ((s = strrchr(t_str, '@')) && check_if_ipmask(s + 1))
-      newban->flags |= BAN_IPMASK;
   }
 
   if (!state->chptr->banlist) {