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;