Warn when using -x with a non-DEBUGMODE ircd.
[ircu2.10.12-pk.git] / ircd / m_silence.c
index 1be8a4b25218ace34081980b53f2634833b6fdae..4530d6bcb7d84c96e983c7768fe0f29fb745b71b 100644 (file)
  * @return The new ban entry on success, NULL on failure.
  */
 static struct Ban *
-apply_silence(struct Client *sptr, const char *mask)
+apply_silence(struct Client *sptr, char *mask)
 {
   struct Ban *sile;
   int flags;
+  char orig_mask[NICKLEN+USERLEN+HOSTLEN+3];
 
   assert(mask && mask[0]);
 
@@ -83,9 +84,22 @@ apply_silence(struct Client *sptr, const char *mask)
     mask++;
   }
 
-  /* Make the silence, set flags, and apply it. */
-  sile = make_ban(mask);
+  /* Make the silence and set additional flags. */
+  ircd_strncpy(orig_mask, mask, sizeof(orig_mask) - 1);
+  sile = make_ban(pretty_mask(mask));
   sile->flags |= flags;
+
+  /* If they're a local user trying to ban too broad a mask, forbid it. */
+  if (MyUser(sptr)
+      && (sile->flags & BAN_IPMASK)
+      && sile->addrbits > 0
+      && sile->addrbits < (irc_in_addr_is_ipv4(&sile->address) ? 112 : 32)) {
+    send_reply(sptr, ERR_MASKTOOWIDE, orig_mask);
+    free_ban(sile);
+    return NULL;
+  }
+
+  /* Apply it to the silence list. */
   return apply_ban(&cli_user(sptr)->silence, sile, 1) ? NULL : sile;
 }
 
@@ -118,11 +132,13 @@ forward_silences(struct Client *sptr, char *silences, struct Client *dest)
     maxlength = maxsiles * feature_int(FEAT_AVBANLEN);
     siles = totlength = 0;
     /* Count number of current silences and their total length. */
+    plast = &cli_user(sptr)->silence;
     for (sile = cli_user(sptr)->silence; sile; sile = sile->next) {
       if (sile->flags & (BAN_OVERLAPPED | BAN_ADD | BAN_DEL))
         continue;
       siles++;
       totlength += strlen(sile->banstr);
+      plast = &sile->next;
     }
     for (ii = jj = 0; ii < ac_count; ++ii) {
       sile = accepted[ii];
@@ -132,12 +148,16 @@ forward_silences(struct Client *sptr, char *silences, struct Client *dest)
       if (!(sile->flags & (BAN_OVERLAPPED | BAN_DEL))) {
         slen = strlen(sile->banstr);
         if ((siles >= maxsiles) || (totlength + slen >= maxlength)) {
+          *plast = NULL;
+          if (MyUser(sptr))
+            send_reply(sptr, ERR_SILELISTFULL, accepted[ii]->banstr);
           free_ban(accepted[ii]);
           continue;
         }
         /* Update counts. */
         siles++;
         totlength += slen;
+        plast = &sile->next;
       }
       /* Store the update. */
       accepted[jj++] = sile;