-#define MASK_16 0xffff
-
-#define IPCHECK_CLONE_LIMIT 2
-#define IPCHECK_CLONE_PERIOD 20
-#define IPCHECK_CLONE_DELAY 1
-
-
-/*----------------------------------------------------------------------------
- * Handy Macros
- *--------------------------------------------------------------------------*/
-#define NOW (CurrentTime)
-#define CONNECTED_SINCE(x) (NOW - (x->last_connect))
-
-
-/*----------------------------------------------------------------------------
- * Global Data (ugly!)
- *--------------------------------------------------------------------------*/
-static ip_reg_entry_t *hashTable[IP_REGISTRY_TABLE_SIZE];
-static ip_reg_entry_t *freeList = 0;
-
-
-/*----------------------------------------------------------------------------
- * ip_registry_hash: Create a hash key for an IP registry entry and return
- * the value. (Is unsigned int really a good type to give
- * to the IP argument? Ugly. This should probably be a
- * struct in_addr. This is asking for trouble. --ZS)
- *--------------------------------------------------------------------------*/
-static unsigned int ip_registry_hash(unsigned int ip) {
- return ((ip >> 16) ^ ip) & (IP_REGISTRY_TABLE_SIZE - 1);
+/** Report current time for tracking in IPRegistryEntry::last_connect. */
+#define NOW ((unsigned short)(CurrentTime & 0xffff))
+/** Time from \a x until now, in seconds. */
+#define CONNECTED_SINCE(x) (NOW - (x))
+
+/** Macro for easy access to configured IPcheck clone limit. */
+#define IPCHECK_CLONE_LIMIT feature_int(FEAT_IPCHECK_CLONE_LIMIT)
+/** Macro for easy access to configured IPcheck clone period. */
+#define IPCHECK_CLONE_PERIOD feature_int(FEAT_IPCHECK_CLONE_PERIOD)
+/** Macro for easy access to configured IPcheck clone delay. */
+#define IPCHECK_CLONE_DELAY feature_int(FEAT_IPCHECK_CLONE_DELAY)
+
+/** Hash table for storing IPRegistryEntry entries. */
+static struct IPRegistryEntry* hashTable[IP_REGISTRY_TABLE_SIZE];
+/** List of allocated but unused IPRegistryEntry structs. */
+static struct IPRegistryEntry* freeList;
+/** Periodic timer to look for too-old registry entries. */
+static struct Timer expireTimer;
+
+/** Convert IP addresses to canonical form for comparison. IPv4
+ * addresses are translated into 6to4 form; IPv6 addresses are left
+ * alone.
+ * @param[out] out Receives canonical format for address.
+ * @param[in] in IP address to canonicalize.
+ */
+static void ip_registry_canonicalize(struct irc_in_addr *out, const struct irc_in_addr *in)
+{
+ if (irc_in_addr_is_ipv4(in)) {
+ out->in6_16[0] = htons(0x2002);
+ out->in6_16[1] = in->in6_16[6];
+ out->in6_16[2] = in->in6_16[7];
+ out->in6_16[3] = out->in6_16[4] = out->in6_16[5] = 0;
+ out->in6_16[6] = out->in6_16[7] = 0;
+ } else
+ memcpy(out, in, sizeof(*out));