Package: ircd-ircu
Version: 2.10.12.10.dfsg1-1
Severity: normal
Tags: patch

We had a switch outage in the office today, causing many people to be
disconnected from IRC.  When they attempted to reconnect, many clients
failed to connect, receiving the message:

 ERROR :Your host is trying to (re)connect too fast -- throttled

I tracked the problem down to line 123 of IPcheck.c where the code makes
an unwarranted assumption that IPv6 addresses should be masked to /64
and IPv4 addresses (after conversion to 6to4 format) should be masked to
/48.

Neither assumption is correct.  Our entire LAN is a /64, and this is not
unusual (at all), and indeed IPv6 address autoconfiguration is exactly
designed for multiple devices to coexist without collisions inside a
/64 subnet.

Furthermore, the assumption is not warranted for IPv4 addresses which
are canonicalised into 6to4 IPv6 addresses and then masked to /48. It is
*expected* that people will configure private networks behind 6to4
gateways, frequently using a /64 network with address autoconfiguration,
resulting in the same kind of issue with masking, and the daemon makes
no attempt to distinguish between an IPv4 address which *it* has
canonicalised, and one which is within the 6to4 address of a realio,
trulio, IPv6 gateway.

The attached patch fixes the problem by setting the mask to /128 when
performing this test at connection time.  It is possible that this
assumption occurs in other places as well, but this is the one causing
us pain right now :-)

Regards,
                                        Andrew McMillan.


-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (990, 'unstable')
Architecture: i386 (i686)

Kernel: Linux 2.6.25.1-hippy (SMP w/2 CPU cores)
Locale: LANG=en_NZ.UTF8, LC_CTYPE=POSIX (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/bash

Versions of packages ircd-ircu depends on:
ii  libc6                         2.7-10     GNU C Library: Shared libraries

ircd-ircu recommends no packages.

-- no debconf information
diff --git a/ircd/IPcheck.c b/ircd/IPcheck.c
index c3cb586..c05d104 100644
--- a/ircd/IPcheck.c
+++ b/ircd/IPcheck.c
@@ -108,8 +108,8 @@ static unsigned int ip_registry_hash(const struct irc_in_addr *ip)
 }
 
 /** Find an IP registry entry if one exists for the IP address.
- * If \a ip looks like an IPv6 address, only consider the first 64 bits
- * of the address. Otherwise, only consider the final 32 bits.
+ * We consider the full 128 bits of any address since there might
+ * potentially be many people on a LAN behind a 6to4 gateway.
  * @param[in] ip IP address to search for.
  * @return Matching registry entry, or NULL if none exists.
  */
@@ -120,8 +120,7 @@ static struct IPRegistryEntry* ip_registry_find(const struct irc_in_addr *ip)
   ip_registry_canonicalize(&canon, ip);
   entry = hashTable[ip_registry_hash(&canon)];
   for ( ; entry; entry = entry->next) {
-    int bits = (canon.in6_16[0] == htons(0x2002)) ? 48 : 64;
-    if (ipmask_check(&canon, &entry->addr, bits))
+    if (ipmask_check(&canon, &entry->addr, 128))
       break;
   }
   return entry;

Reply via email to