[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: IP masks support for modes in channels (patch) (fwd)



---------- Forwarded message ----------
Date: Sat, 16 Sep 2000 09:03:22 +0200 (CEST)
From: Kuba Pamirski <crio@xxxxxxxxxxxxx>
To: ircd-dev@xxxxxxx
Subject: IP masks support for modes in channels (patch)

Hello,

 I did what I've been actually thinking about for a longer period of time
- implemented netmasks support for +b/+e/+I channel modes. It is partially
based on ircd/s_conf.c match_ipmask() code. It has been tested with
v6-enabled ircd 2.10.3p1 and should hopefully work both for v4 and v6
compiled daemons. This patch finnally makes channel
bans/invitations/exempts be more precise. It won't break The Protocol
since you could previously /mode #chan +b
*!*@0:0:0:0:0:ffff:150.254.176.0/124 but it wouldn't work. Now it does...

Later I could modify this patch a bit so that the daemon might recognize
duplicate (redundant) modes, for example dissallow banning
*!*@150.254.176.0/28 when *!*@150.254.176.0/26 ban is present.

Kuba /crio/ Pamirski

...and here goes the diff...

--- irc2.10.3/ircd/channel.c	Wed Aug 23 15:49:24 2000
+++ irc2.10.3-dbg/ircd/channel.c	Sat Sep 16 08:36:39 2000
@@ -263,4 +263,5 @@
 /*
  * match_modeid - returns a pointer to the mode structure if matching else NULL
+ * modified to support netmasks in +b/+e/+I channel modes -- crio /16.09.2000/
  */
 static	Link	*match_modeid(type, cptr, chptr)
@@ -270,5 +271,12 @@
 {
 	Reg	Link	*tmp;
-	char	*s;
+	char	*s, *pa, *pm;
+	char	dummy[128];
+	u_long	lmask;
+	int	mval;
+	struct IN_ADDR	addr;
+#ifdef INET6
+	int	j;
+#endif
 
 	if (!IsPerson(cptr))
@@ -299,7 +307,71 @@
 	    
 			for (tmp = chptr->mlist; tmp; tmp = tmp->next)
-				if (tmp->flags == type &&
-				    match(tmp->value.cp, s) == 0)
-					break;
+				if (tmp->flags == type)
+				  if (index(index(tmp->value.cp, '@'),
+				  	'/')==NULL)
+				    {
+				       if (match(tmp->value.cp, s) == 0)
+					  break;
+				    }
+				  else
+				    {
+				       strncpyzt(dummy, tmp->value.cp,
+				       			 sizeof(dummy));
+				       pa = index(dummy, '@') + 1;
+				       
+				       /* Improper use - hostname couldn't
+				          start with '/' character */
+
+				       if ((pm = index(pa, '/')) == pa + 1)
+				          continue;
+				       
+				       *pm = '\0';
+				       mval = atoi(pm + 1);
+#ifndef INET6
+				       if (mval < 0 || mval > 32)
+				          continue;
+				       
+				       lmask = htonl((u_long)
+				       		0xffffffffL << (32-m));
+				       addr.s_addr = inetaddr(pa);
+				       if (((addr.s_addr ^ cptr->ip.s_addr) &
+				       				 lmask))
+				          continue;
+#else
+				       if (mval < 0 || mval > 128)
+				          continue;
+				       
+				       inet_pton(AF_INET6, pa,
+				       		 (void *)addr.s6_addr);
+				       j = mval & 0x1f;
+				       mval >>= 5;
+				       
+				       if (mval & memcmp((void *)addr.s6_addr,
+				       		(void *)(cptr->ip.s6_addr),
+				       				 mval << 2))
+				       		continue;
+				       		
+				       if (j)
+				       {
+				       		lmask = htonl((u_long)
+				       			0xffffffffL << (32-j));
+				       		if ((((u_int32_t *)
+				       			(addr.s6_addr))[mval] ^
+				       			((u_int32_t *)
+				       			(cptr->ip.s6_addr))
+				       			[mval]) & lmask)
+				       			continue;
+				       }
+#endif
+				       /* Substitute original mode's hostname
+				          with '*' wildcard since ip number has
+				          been positively matched above */
+
+				       *pa = '*';
+				       pa[1] = '\0';
+
+				       if (match(dummy, s) == 0)
+					  break;
+				    }
 		    }
 	  }