diff -uNrd ircd-ratbox/doc/example.conf ircd-ratbox-hostmask/doc/example.conf
--- ircd-ratbox/doc/example.conf	Mon Jul 26 09:04:16 2004
+++ ircd-ratbox-hostmask/doc/example.conf	Sat Jul 31 13:04:11 2004
@@ -830,11 +830,6 @@
 	 */
 	client_flood = 20;
 
-        /* use_whois_actually: send clients requesting a whois a numeric
-         * giving the real IP of non-spoofed clients to prevent DNS abuse.
-         */
-        use_whois_actually = yes;
-
 	/* usermodes configurable: a list of usermodes for the options below
 	 *
 	 * +b - bots       - See bot and drone flooding notices
diff -uNrd ircd-ratbox/include/client.h ircd-ratbox-hostmask/include/client.h
--- ircd-ratbox/include/client.h	Mon Jul 19 15:04:32 2004
+++ ircd-ratbox-hostmask/include/client.h	Sat Jul 31 13:03:05 2004
@@ -150,6 +150,7 @@
 	 * considered a read-only field after the client has registered.
 	 */
 	char host[HOSTLEN + 1];	/* client's hostname */
+	char realhost[HOSTLEN + 1]; /* client's real hostname */
 	char sockhost[HOSTIPLEN + 1]; /* clients ip */
 	char info[REALLEN + 1];	/* Free form additional client info */
 
@@ -334,6 +335,8 @@
 #define has_id(source)	((source)->id[0] != '\0')
 #define use_id(source)	((source)->id[0] != '\0' ? (source)->id : (source)->name)
 
+#define has_mask(x)	((x)->umodes & UMODE_IPMASK)
+
 /* if target is TS6, use id if it has one, else name */
 #define get_id(source, target) ((IsServer(target->from) && has_id(target->from)) ? \
 				use_id(source) : (source)->name)
@@ -379,6 +382,8 @@
 #define UMODE_OPER         0x20000	/* Operator */
 #define UMODE_ADMIN        0x40000	/* Admin on server */
 
+#define UMODE_IPMASK       0x80000	/* Host mask applied */
+
 #define UMODE_ALL	   UMODE_SERVNOTICE
 
 /* overflow flags */
@@ -395,7 +400,8 @@
 #define FLAGS2_EXEMPTSHIDE	0x40000000
 
 #define SEND_UMODES  (UMODE_INVISIBLE | UMODE_OPER | UMODE_WALLOP | \
-                      UMODE_ADMIN)
+                      UMODE_ADMIN | UMODE_IPMASK)
+
 #define DEFAULT_OPER_UMODES (UMODE_SERVNOTICE | UMODE_OPERWALL | \
                              UMODE_WALLOP | UMODE_LOCOPS)
 #define ALL_UMODES   (SEND_UMODES | UMODE_SERVNOTICE | UMODE_CCONN | \
diff -uNrd ircd-ratbox/include/numeric.h ircd-ratbox-hostmask/include/numeric.h
--- ircd-ratbox/include/numeric.h	Wed Jun 16 18:24:20 2004
+++ ircd-ratbox-hostmask/include/numeric.h	Sat Jul 31 13:03:05 2004
@@ -182,12 +182,15 @@
 #define RPL_ENDOFBANLIST     368
 /* rpl_endofwhowas above (369) */
 
+
 #define RPL_INFO             371
 #define RPL_MOTD             372
 #define RPL_INFOSTART        373
 #define RPL_ENDOFINFO        374
 #define RPL_MOTDSTART        375
 #define RPL_ENDOFMOTD        376
+
+#define RPL_WHOISHOST        378
 
 #define RPL_YOUREOPER        381
 #define RPL_REHASHING        382
diff -uNrd ircd-ratbox/include/s_serv.h ircd-ratbox-hostmask/include/s_serv.h
--- ircd-ratbox/include/s_serv.h	Sun Apr 11 19:26:41 2004
+++ ircd-ratbox-hostmask/include/s_serv.h	Sat Jul 31 13:03:05 2004
@@ -71,10 +71,13 @@
 #define CAP_ENCAP	0x04000	/* supports ENCAP */
 #define CAP_TS6		0x08000 /* supports TS6 or above */
 
+#define CAP_IPMASK	0x10000 /* supports host masking */
+
 #define CAP_MASK        (CAP_QS  | CAP_EX   | CAP_CHW  | \
                          CAP_IE  | CAP_KLN  | \
                          CAP_GLN | CAP_CLUSTER | CAP_ENCAP | \
-                         CAP_ZIP  | CAP_KNOCK  | CAP_UNKLN)
+                         CAP_ZIP  | CAP_KNOCK  | CAP_UNKLN | \
+			 CAP_IPMASK)
 
 #ifdef HAVE_LIBZ
 #define CAP_ZIP_SUPPORTED       CAP_ZIP
@@ -156,5 +159,6 @@
 extern int server_estab(struct Client *client_p);
 
 extern int serv_connect(struct server_conf *, struct Client *);
+int make_virthost (char *, char *, char *);
 
 #endif /* INCLUDED_s_serv_h */
diff -uNrd ircd-ratbox/include/whowas.h ircd-ratbox-hostmask/include/whowas.h
--- ircd-ratbox/include/whowas.h	Mon Mar 15 10:58:00 2004
+++ ircd-ratbox-hostmask/include/whowas.h	Sat Jul 31 13:03:05 2004
@@ -52,6 +52,7 @@
 	char name[NICKLEN + 1];
 	char username[USERLEN + 1];
 	char hostname[HOSTLEN + 1];
+	char realhost[HOSTLEN + 1];
 	const char *servername;
 	char realname[REALLEN + 1];
 	time_t logoff;
diff -uNrd ircd-ratbox/modules/Makefile.in ircd-ratbox-hostmask/modules/Makefile.in
--- ircd-ratbox/modules/Makefile.in	Thu Jun 17 16:18:48 2004
+++ ircd-ratbox-hostmask/modules/Makefile.in	Sat Jul 31 13:03:05 2004
@@ -63,6 +63,7 @@
   m_etrace.c \
   m_gline.c \
   m_help.c \
+  m_hostmask.c \
   m_info.c \
   m_invite.c \
   m_ison.c \
@@ -87,6 +88,7 @@
   m_set.c \
   m_stats.c \
   m_svinfo.c \
+  m_svshost.c \
   m_tb.c \
   m_testline.c \
   m_testmask.c \
diff -uNrd ircd-ratbox/modules/core/m_nick.c ircd-ratbox-hostmask/modules/core/m_nick.c
--- ircd-ratbox/modules/core/m_nick.c	Sun Apr  4 19:38:01 2004
+++ ircd-ratbox-hostmask/modules/core/m_nick.c	Sat Jul 31 13:03:05 2004
@@ -341,16 +341,16 @@
 	}
 
 	/* check the length of the clients gecos */
-	if(strlen(parv[8]) > REALLEN)
+	if(strlen(parv[(parc > 9)? 9 : 8]) > REALLEN)
 	{
-		char *s = LOCAL_COPY(parv[8]);
+		char *s = LOCAL_COPY(parv[(parc > 9)? 9 : 8]);
 		/* why exactly do we care? --fl */
 		sendto_realops_flags(UMODE_ALL, L_ALL,
 				"Long realname from server %s for %s", parv[7],
 				parv[1]);
 
 		s[REALLEN] = '\0';
-		parv[8] = s;
+		parv[(parc > 9)? 9 : 8] = s;
 	}
 
 	newts = atol(parv[3]);
@@ -390,6 +390,10 @@
  *     parv[6] - hostname
  *     parv[7] - IP
  *     parv[8] - UID
+ *  IPMASK:
+ *     parv[9] - real hostname
+ *     parv[10] - gecos
+ *  NORMAL:
  *     parv[9] - gecos
  */
 static int
@@ -441,13 +445,13 @@
 	}
 
 	/* check length of clients gecos */
-	if(strlen(parv[9]) > REALLEN)
+	if(strlen(parv[(parc > 10)? 10 : 9]) > REALLEN)
 	{
-		char *s = LOCAL_COPY(parv[9]);
+		char *s = LOCAL_COPY(parv[(parc > 10)? 10 : 9]);
 		sendto_realops_flags(UMODE_ALL, L_ALL, "Long realname from server %s for %s",
 				     parv[0], parv[1]);
 		s[REALLEN] = '\0';
-		parv[9] = s;
+		parv[(parc > 10)? 10 : 9] = s;
 	}
 
 	target_p = find_client(parv[1]);
@@ -903,11 +907,11 @@
 	strcpy(source_p->name, nick);
 	strlcpy(source_p->username, parv[5], sizeof(source_p->username));
 	strlcpy(source_p->host, parv[6], sizeof(source_p->host));
-	
-	if(parc == 10)
+
+	if((parc == 10 || parc == 11) && (server != NULL))
 	{
 		user->server = find_or_add(server->name);
-		strlcpy(source_p->info, parv[9], sizeof(source_p->info));
+		strlcpy(source_p->info, parv[(parc > 10)? 10 : 9], sizeof(source_p->info));
 		strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
 		strlcpy(source_p->id, parv[8], sizeof(source_p->id));
 		add_to_id_hash(source_p->id, source_p);
@@ -915,7 +919,11 @@
 	else
 	{
 		user->server = find_or_add(parv[7]);
-		strlcpy(source_p->info, parv[8], sizeof(source_p->info));
+		strlcpy(source_p->info, parv[(parc > 9)? 9 : 8], sizeof(source_p->info));
+		if (parc > 9)
+			strlcpy (source_p->realhost, parv[8], sizeof(source_p->realhost));
+		else
+			strlcpy (source_p->realhost, "unavailable", sizeof(source_p->realhost));
 	}
 
 	/* remove any nd entries for this nick */
diff -uNrd ircd-ratbox/modules/m_hostmask.c ircd-ratbox-hostmask/modules/m_hostmask.c
--- ircd-ratbox/modules/m_hostmask.c	Wed Dec 31 17:00:00 1969
+++ ircd-ratbox-hostmask/modules/m_hostmask.c	Sat Jul 31 13:03:05 2004
@@ -0,0 +1,38 @@
+#include "stdinc.h"
+#include "modules.h"
+#include "hook.h"
+#include "client.h"
+#include "ircd.h"
+#include "send.h"
+#include "s_conf.h"
+#include "s_serv.h"
+#include "s_newconf.h"
+#include "s_user.h"
+#include "hash.h"
+
+static int ms_rhost (struct Client *, struct Client *, int, const char **);
+
+struct Message rhost_msgtab = {
+  "RHOST", 0, 0, 0, MFLG_SLOW,
+  { mg_ignore, mg_ignore, mg_ignore, { ms_rhost, 2 }, mg_ignore, mg_ignore }
+};
+
+mapi_clist_av1 hostmask_clist[] = { &rhost_msgtab, NULL };
+
+DECLARE_MODULE_AV1(hostmask, NULL, NULL, hostmask_clist, NULL, NULL, "$Revision: 1.0 $ $Author: $");
+
+
+static int ms_rhost (struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+{
+	struct Client *target_p = NULL;
+
+	sendto_server (client_p, NULL, CAP_IPMASK, NOCAPS, ":%s RHOST %s :%s", parv[0], parv[1], parv[2]);
+
+	if ((target_p = find_client (parv[1])) != NULL)
+	{
+		strlcpy (target_p->realhost, parv[2], sizeof(target_p->realhost));
+		return 0;
+	}
+
+	return 0;
+}
diff -uNrd ircd-ratbox/modules/m_svshost.c ircd-ratbox-hostmask/modules/m_svshost.c
--- ircd-ratbox/modules/m_svshost.c	Wed Dec 31 17:00:00 1969
+++ ircd-ratbox-hostmask/modules/m_svshost.c	Sat Jul 31 14:32:11 2004
@@ -0,0 +1,57 @@
+#include "stdinc.h"
+#include "modules.h"
+#include "hook.h"
+#include "client.h"
+#include "hash.h"
+#include "ircd.h"
+#include "send.h"
+#include "s_serv.h"
+#include "s_newconf.h"
+
+static int ms_svshost (struct Client *, struct Client *, int, const char **);
+static int mo_svshost (struct Client *, struct Client *, int, const char **);
+
+struct Message svshost_msgtab = {
+	"SVSHOST", 0, 0, 0, MFLG_SLOW,
+	{ mg_ignore, mg_ignore, { ms_svshost, 0 }, { ms_svshost, 0 }, mg_ignore, mg_ignore }
+};
+
+struct Message chghost_msgtab = {
+	"CHGHOST", 0, 0, 0, MFLG_SLOW,
+	{ mg_ignore, mg_ignore, mg_ignore, mg_ignore, mg_ignore, { mo_svshost, 3 } }
+};
+
+struct Message sethost_msgtab = {
+	"SETHOST", 0, 0, 0, MFLG_SLOW,
+	{ mg_ignore, mg_ignore, mg_ignore, mg_ignore, mg_ignore, { mo_svshost, 3 } }
+};
+
+mapi_clist_av1 svshost_clist[] = { &svshost_msgtab, &chghost_msgtab, &sethost_msgtab, NULL };
+
+DECLARE_MODULE_AV1(svshost, NULL, NULL, svshost_clist, NULL, NULL, "$Revision 1.4 $");
+
+static int ms_svshost (struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+{
+	struct Client *target_p;
+
+	if (parc < 3)
+		return 0;
+
+	sendto_server (source_p, NULL, CAP_IPMASK, NOCAPS, ":%s SVSHOST %s :%s", parv[0], parv[1], parv[2]);
+
+
+	target_p = find_client (parv[1]);
+
+	if (target_p == NULL)
+		return -1;
+
+	strlcpy (target_p->host, parv[2], sizeof(target_p->host));
+
+	return 0;
+}
+
+static int mo_svshost (struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+{
+	ilog (L_MAIN, "mo_svshost with %d parameters", parc);
+	return 0;
+}
diff -uNrd ircd-ratbox/modules/m_whois.c ircd-ratbox-hostmask/modules/m_whois.c
--- ircd-ratbox/modules/m_whois.c	Mon Apr  5 12:46:20 2004
+++ ircd-ratbox-hostmask/modules/m_whois.c	Sat Jul 31 13:03:56 2004
@@ -283,6 +283,9 @@
 			   target_p->name, target_p->user->server,
 			   a2client_p ? a2client_p->info : "*Not On This Net*");
 
+	if((IsOper(source_p)) || (target_p == source_p))
+		sendto_one_numeric(source_p, RPL_WHOISHOST, form_str(RPL_WHOISHOST), target_p->name, target_p->realhost);
+
 	if(target_p->user->away)
 		sendto_one_numeric(source_p, RPL_AWAY, form_str(RPL_AWAY),
 				   target_p->name, target_p->user->away);
@@ -297,11 +300,6 @@
 
 	if(MyClient(target_p))
 	{
-		if(ConfigFileEntry.use_whois_actually && show_ip(source_p, target_p))
-			sendto_one_numeric(source_p, RPL_WHOISACTUALLY,
-					   form_str(RPL_WHOISACTUALLY),
-					   target_p->name, target_p->sockhost);
-
 		sendto_one_numeric(source_p, RPL_WHOISIDLE, form_str(RPL_WHOISIDLE),
 				   target_p->name, 
 				   CurrentTime - target_p->user->last, 
@@ -309,14 +307,6 @@
 	}
 	else
 	{
-		if(ConfigFileEntry.use_whois_actually && show_ip(source_p, target_p) &&
-		   !EmptyString(target_p->sockhost) && strcmp(target_p->sockhost, "0"))
-		{
-			sendto_one_numeric(source_p, RPL_WHOISACTUALLY,
-					   form_str(RPL_WHOISACTUALLY),
-					   target_p->name, target_p->sockhost);
-			
-		}
 	
 	}
 
diff -uNrd ircd-ratbox/modules/m_whowas.c ircd-ratbox-hostmask/modules/m_whowas.c
--- ircd-ratbox/modules/m_whowas.c	Mon Mar 15 10:58:03 2004
+++ ircd-ratbox-hostmask/modules/m_whowas.c	Sat Jul 31 13:03:05 2004
@@ -104,7 +104,8 @@
 		{
 			sendto_one(source_p, form_str(RPL_WHOWASUSER),
 				   me.name, source_p->name, temp->name,
-				   temp->username, temp->hostname, temp->realname);
+				   temp->username,
+                                   (IsAdmin(source_p))? temp->realhost : temp->hostname, temp->realname);
 
 			sendto_one_numeric(source_p, RPL_WHOISSERVER,
 					   form_str(RPL_WHOISSERVER),
diff -uNrd ircd-ratbox/src/Makefile.in ircd-ratbox-hostmask/src/Makefile.in
--- ircd-ratbox/src/Makefile.in	Thu Jun 17 16:18:57 2004
+++ ircd-ratbox-hostmask/src/Makefile.in	Sat Jul 31 13:03:05 2004
@@ -70,6 +70,7 @@
   kdparse.c			\
   linebuf.c                     \
   listener.c                    \
+  mask.c			\
   match.c                       \
   memory.c                      \
   modules.c                     \
diff -uNrd ircd-ratbox/src/client.c ircd-ratbox-hostmask/src/client.c
--- ircd-ratbox/src/client.c	Sat Jul 24 08:14:45 2004
+++ ircd-ratbox-hostmask/src/client.c	Sat Jul 31 13:03:05 2004
@@ -1490,7 +1490,7 @@
 	sendto_realops_flags(UMODE_CCONN, L_ALL,
 			     "Client exiting: %s (%s@%s) [%s] [%s]",
 			     source_p->name,
-			     source_p->username, source_p->host, comment,
+			     source_p->username, source_p->realhost, comment,
 #ifdef HIDE_SPOOF_IPS
                              IsIPSpoof(source_p) ? "255.255.255.255" :
 #endif
diff -uNrd ircd-ratbox/src/mask.c ircd-ratbox-hostmask/src/mask.c
--- ircd-ratbox/src/mask.c	Wed Dec 31 17:00:00 1969
+++ ircd-ratbox-hostmask/src/mask.c	Sat Jul 31 13:03:05 2004
@@ -0,0 +1,268 @@
+/*
+ *  mask.c: Provides Hostname Masking
+ *
+ *  Copyright (C) 2000-2002 Edward Brocklesby, Hybrid Development Team
+ *  Copyright (C) 2004 J. Johston, FreeWorld-ircd Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *  USA
+ *
+ *  $Id: cloak.c,v 1.8 2002/10/23 03:53:22 fishwaldo Exp $
+ */
+
+#include "stdinc.h"
+#include "whowas.h"
+#include "client.h"
+#include "common.h"
+#include "hash.h"
+#include "irc_string.h"
+#include "ircd.h"
+#include "ircd_defs.h"
+#include "numeric.h"
+#include "s_serv.h"
+#include "s_user.h"
+#include "send.h"
+#include "s_conf.h"
+#include "memory.h"
+#include "s_log.h"
+#include "sprintf_irc.h"
+
+#define KEY 23857
+#define KEY2 38447
+#define KEY3 64709
+
+int str2arr		(char **, char *, char *);
+unsigned long crc32	(const unsigned char *s, unsigned int len);
+#ifdef IPV6
+void get_domain		(char *, char *);
+#endif
+
+static unsigned long crc32_tab[] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+
+unsigned long crc32 (const unsigned char *s, unsigned int len)
+{
+  unsigned int i;
+  unsigned long crc32val;
+
+  crc32val = 0;
+  for (i = 0; i < len; i++)
+    {
+      crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
+    }
+  return crc32val;
+}
+
+int str2arr (char **pparv, char *string, char *delim)
+{
+  char *tok;
+  int pparc = 0;
+
+  tok = (char *) strtok (string, delim);
+  while (tok != NULL)
+    {
+      pparv[pparc++] = tok;
+      tok = (char *) strtok (NULL, delim);
+    }
+
+  return pparc;
+}
+
+int make_virthost (char *curr, char *host, char *new)
+{
+  static char mask[HOSTLEN + 1];
+  char *parv[HOSTLEN + 1], *parv2[HOSTLEN + 1], s[HOSTLEN + 1],
+    s2[HOSTLEN + 2];
+  int parc = 0, parc2 = 0, len = 0;
+  unsigned long hash[8];
+  char thostbuf[HOSTLEN];
+
+  if (!valid_hostname(curr))
+    return -1;
+
+#ifdef IPV6
+  if (strchr (host, ':'))
+  {
+    get_domain (thostbuf, host);
+    sprintf (mask, "%s", thostbuf);
+    strncpy (new, mask, HOSTLEN);
+    return 0;
+  }
+#endif
+
+  strncpy (s2, curr, HOSTLEN);
+  strncpy (s, host, HOSTLEN);
+
+  parc = str2arr (parv, s, ".");
+  parc2 = str2arr (parv2, s2, ".");
+
+  hash[0] = ((crc32 (parv[3], strlen (parv[3])) + KEY2) ^ KEY) ^ KEY3;
+  hash[1] = ((crc32 (parv[2], strlen (parv[2])) + KEY2) ^ KEY) ^ KEY3;
+
+
+  hash[0] <<= 2;
+  hash[0] >>= 2;
+
+  hash[1] <<= 2;
+  hash[1] >>= 2;
+
+  if (parc2 == 4 || parc2 < 2)
+    {
+      len = strlen (parv2[3]);
+      if (strchr ("0123456789", parv2[3][len - 1]) || parc2 < 2)
+        {
+          hash[2] = ((crc32 (parv[1], strlen (parv[1])) + KEY2) ^ KEY) ^ KEY3;
+          hash[3] = ((crc32 (parv[0], strlen (parv[0])) + KEY2) ^ KEY) ^ KEY3;
+
+          hash[2] <<= 2;
+          hash[2] >>= 2;
+
+          hash[3] <<= 2;
+          hash[3] >>= 2;
+
+          sprintf (mask, "%lx.%lx.%lx.%lx.IP", hash[0], hash[1], hash[2], hash[3]);
+        }
+      else
+        {
+          sprintf (mask, "%s-%lx.%lx.%s.%s.%s",
+                      ServerInfo.network_name, hash[0], hash[1], parv2[parc2 - 3], parv2[parc2 - 2],
+                      parv2[parc2 - 1]);
+        }
+    }
+  else
+    {
+      if (parc2 >= 4)
+        {
+          sprintf (mask, "%s-%lx.%lx.%s.%s.%s",
+                      ServerInfo.network_name, hash[0], hash[1], parv2[parc2 - 3], parv2[parc2 - 2],
+                      parv2[parc2 - 1]);
+        }
+      else
+        {
+          sprintf (mask, "%s-%lx.%lx.%s.%s",
+                      ServerInfo.network_name, hash[0], hash[1], parv2[parc2 - 2], parv2[parc2 - 1]);
+        }
+    }
+  strncpy (new, mask, HOSTLEN);
+  ilog (L_MAIN, "mask created: %s", mask);
+  return 1;
+}
+
+void get_domain(char *key, char *hostname)
+{
+  char *dptr;
+  char tbuf[HOSTLEN];
+  int len;
+
+  strlcpy(tbuf, hostname, HOSTLEN);
+  len = strlen(tbuf);
+
+  ilog (L_MAIN, "get_domain(??, %s);", hostname);
+
+  dptr = strchr(tbuf, ':');
+  if (dptr != NULL)
+  {
+#ifdef AF_INET6
+    struct in6_addr iaddr6;
+
+    /* If there's a '.' at the end of the IPv6 IP, that will cause problems
+    ** with some inet_pton()'s.  Remove it.  This happens if dot_in_ip6_addr
+    ** is set on in Hybrid 7/ircd-ratbox.
+    */
+    if (tbuf[len - 1] == '.')
+    {
+      tbuf[len - 1] = '\0';
+      /* Not really needed:  len--; */
+    }
+    inet_pton(AF_INET6, tbuf, &iaddr6);
+    /* This is cheating...apply a /96 mask by clearing
+    ** a value in the in6_addr
+    ** (or /64)
+    */
+    /* Ugh, it appears the only compatible thing with in6_addr
+    ** is the name s6_addr.  It LOOKS like most OS's define
+    ** s6_addr as an array of 16 uint8_t's
+    */
+    iaddr6.s6_addr[8] = 0;
+    iaddr6.s6_addr[9] = 0;
+    iaddr6.s6_addr[10] = 0;
+    iaddr6.s6_addr[11] = 0;
+
+    inet_ntop(AF_INET6, &iaddr6, tbuf, HOSTLEN);
+    strlcpy(key, tbuf, HOSTLEN);
+#else
+    /* XXX Choose a better way to handle when we can't deal with IPv6
+    ** addresses (Cygwin)
+    */
+    strlcpy(key, hostname, HOSTLEN);
+#endif
+
+    ilog (L_MAIN, "key: %s", key);
+
+    return ;
+  }
+}
diff -uNrd ircd-ratbox/src/messages.tab ircd-ratbox-hostmask/src/messages.tab
--- ircd-ratbox/src/messages.tab	Wed Jun 16 18:24:27 2004
+++ ircd-ratbox-hostmask/src/messages.tab	Sat Jul 31 13:03:05 2004
@@ -24,7 +24,7 @@
 /* 001  RPL_WELCOME, */ ":%s 001 %s :Welcome to the %s Internet Relay Chat Network %s",
 /* 002  RPL_YOURHOST,*/ ":%s 002 %s :Your host is %s, running version %s",
 /* 003  RPL_CREATED, */ ":%s 003 %s :This server was created %s",
-/* 004  RPL_MYINFO, */ ":%s 004 %s %s %s oiwszcerkfydnxbaugl biklmnopstveI bkloveI",
+/* 004  RPL_MYINFO, */ ":%s 004 %s %s %s oiwszcerkfydnxbauglX biklmnopstveI bkloveI",
 /* 005  RPL_ISUPPORT, */ "%s :are supported by this server",
 /* 006 */       NULL,
 /* 007 */       NULL,
@@ -400,7 +400,7 @@
 /* 375 RPL_MOTDSTART, */        ":%s 375 %s :- %s Message of the Day - ",
 /* 376 RPL_ENDOFMOTD, */        ":%s 376 %s :End of /MOTD command.",
 /* 377 */       NULL,
-/* 378 */       NULL,
+/* 378 RPL_WHOISHOST, */        "%s :is connected from *@%s",
 /* 379 */       NULL,
 /* 380 */       NULL,
 /* 381 RPL_YOUREOPER, */        ":%s 381 %s :You have entered... the anti-alz Zone!.",
diff -uNrd ircd-ratbox/src/newconf.c ircd-ratbox-hostmask/src/newconf.c
--- ircd-ratbox/src/newconf.c	Sat Jul 24 18:20:23 2004
+++ ircd-ratbox-hostmask/src/newconf.c	Sat Jul 31 13:04:28 2004
@@ -2019,12 +2019,6 @@
 }
 
 static void
-conf_set_general_use_whois_actually(void *data)
-{
-	ConfigFileEntry.use_whois_actually = *(unsigned int *) data;
-}
-
-static void
 conf_set_general_tkline_expire_notices(void *data)
 {
 	ConfigFileEntry.tkline_expire_notices = *(unsigned int *) data;
@@ -2602,8 +2596,6 @@
 	add_conf_item("general", "servlink_path", CF_QSTRING, conf_set_general_servlink_path);
 	add_conf_item("general", "tkline_expire_notices", CF_YESNO,
 		      conf_set_general_tkline_expire_notices);
-	add_conf_item("general", "use_whois_actually", CF_YESNO,
-		      conf_set_general_use_whois_actually);
 	add_conf_item("general", "compression_level", CF_INT, conf_set_general_compression_level);
 	add_conf_item("general", "client_flood", CF_INT, conf_set_general_client_flood);
 	add_conf_item("general", "havent_read_conf", CF_YESNO, conf_set_general_havent_read_conf);
diff -uNrd ircd-ratbox/src/s_conf.c ircd-ratbox-hostmask/src/s_conf.c
--- ircd-ratbox/src/s_conf.c	Mon Jul 26 09:04:21 2004
+++ ircd-ratbox-hostmask/src/s_conf.c	Sat Jul 31 13:03:05 2004
@@ -324,6 +324,19 @@
 		if(IsConfDoIdentd(aconf))
 			SetNeedId(client_p);
 
+		strlcpy (client_p->realhost, client_p->host, sizeof(client_p->realhost));
+
+		if(!IsConfDoSpoofIp(aconf))
+		{
+			if ((make_virthost(client_p->host, client_p->sockhost, client_p->host)) > 0)
+				client_p->umodes |= UMODE_IPMASK;
+			else
+			{
+				ilog (L_MAIN, "Could not mask user: %s!%s@%s", client_p->name, client_p->username, client_p->host);
+				sendto_realops_flags(UMODE_ALL, L_ALL, "Could not mask user: %s!%s@%s", client_p->name, client_p->username, client_p->host);
+			}
+		}
+
 		/* Thanks for spoof idea amm */
 		if(IsConfDoSpoofIp(aconf))
 		{
diff -uNrd ircd-ratbox/src/s_serv.c ircd-ratbox-hostmask/src/s_serv.c
--- ircd-ratbox/src/s_serv.c	Tue Jul 20 12:51:04 2004
+++ ircd-ratbox-hostmask/src/s_serv.c	Sat Jul 31 13:03:05 2004
@@ -99,6 +99,8 @@
 	{ "UNKLN",	CAP_UNKLN},
 	{ "CLUSTER",	CAP_CLUSTER},
 	{ "ENCAP",	CAP_ENCAP },
+	{ "IPMASK",	CAP_IPMASK },
+	{ "MASKIP",	CAP_IPMASK },
 	{0, 0}
 };
 
@@ -720,6 +722,11 @@
 			   target_p->username, target_p->host,
 			   target_p->user->server, target_p->info);
 
+		ilog (L_MAIN, "Sending sendto_one %s:%d", __FILE__, __LINE__);
+		if(IsCapable(client_p, CAP_IPMASK))
+			sendto_one(client_p, ":%s RHOST %s :%s",
+				me.name, target_p->name, target_p->realhost);
+
 		if(ConfigFileEntry.burst_away && !EmptyString(target_p->user->away))
 			sendto_one(client_p, ":%s AWAY :%s",
 				   target_p->name, target_p->user->away);
@@ -850,6 +857,11 @@
 					ubuf,
 					target_p->username, target_p->host,
 					target_p->user->server, target_p->info);
+
+		ilog (L_MAIN, "Sending sendto_one %s:%d", __FILE__, __LINE__);
+		if(IsCapable(client_p, CAP_IPMASK))
+			sendto_one(client_p, ":%s RHOST %s :%s",
+				me.name, target_p->name, target_p->realhost);
 
 		if(ConfigFileEntry.burst_away && !EmptyString(target_p->user->away))
 			sendto_one(client_p, ":%s AWAY :%s",
diff -uNrd ircd-ratbox/src/s_user.c ircd-ratbox-hostmask/src/s_user.c
--- ircd-ratbox/src/s_user.c	Tue Jul 20 08:47:29 2004
+++ ircd-ratbox-hostmask/src/s_user.c	Sat Jul 31 14:28:06 2004
@@ -32,6 +32,7 @@
 #include "client.h"
 #include "common.h"
 #include "hash.h"
+#include "hostmask.h"
 #include "irc_string.h"
 #include "sprintf_irc.h"
 #include "ircd.h"
@@ -85,6 +86,7 @@
 	{UMODE_UNAUTH,		'u'},
 	{UMODE_WALLOP,		'w'},
 	{UMODE_EXTERNAL,	'x'},
+	{UMODE_IPMASK,		'X'},
 	{UMODE_SPY,		'y'},
 	{UMODE_OPERWALL,	'z'},
 	{UMODE_OPERSPY,		'Z'},
@@ -121,7 +123,7 @@
 	0,			/* U */
 	0,			/* V */
 	0,			/* W */
-	0,			/* X */
+	UMODE_IPMASK,		/* X */
 	0,			/* Y */
 	UMODE_OPERSPY,		/* Z */
 	/* 0x5B */ 0, 0, 0, 0, 0, 0, /* 0x60 */
@@ -341,7 +343,7 @@
 			strlcat(source_p->host, ".", sizeof(source_p->host));
 #endif
  	}
- 
+
 
 	aconf = source_p->localClient->att_conf;
 
@@ -476,7 +478,7 @@
 
 	sendto_realops_flags(UMODE_CCONN, L_ALL,
 			     "Client connecting: %s (%s@%s) [%s] {%s} [%s]",
-			     nick, source_p->username, source_p->host,
+			     nick, source_p->username, source_p->realhost,
 #ifdef HIDE_SPOOF_IPS
 			     IsIPSpoof(source_p) ? "255.255.255.255" :
 #endif
@@ -561,30 +563,42 @@
 			strlcat(sockhost, source_p->sockhost, sizeof(sockhost));
 		} else
 			strcpy(sockhost, source_p->sockhost);
-		
+
 		sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
-			      ":%s UID %s %d %ld %s %s %s %s %s :%s",
-			      source_p->servptr->id, nick,
-			      source_p->hopcount + 1,
-			      (long) source_p->tsinfo, ubuf,
-			      source_p->username, source_p->host,
-			      IsIPSpoof(source_p) ? "0" : sockhost,
-			      source_p->id, source_p->info);
+                              ":%s UID %s %d %ld %s %s %s %s %s :%s",
+                              source_p->servptr->id, nick,
+                              source_p->hopcount + 1,
+                              (long) source_p->tsinfo, ubuf,
+                              source_p->username, source_p->host,
+                              IsIPSpoof(source_p) ? "0" : sockhost,
+                              source_p->id, source_p->info);
+
+                sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
+                              "NICK %s %d %ld %s %s %s %s :%s",
+                              nick, source_p->hopcount + 1,
+                              (long) source_p->tsinfo,
+                              ubuf, source_p->username, source_p->host,
+                              user->server, source_p->info);
+
+		sendto_server(client_p, NULL, CAP_IPMASK, NOCAPS,
+				":%s RHOST %s :%s", me.name, source_p->name,
+				source_p->realhost);
+
 
-		sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
-			      "NICK %s %d %ld %s %s %s %s :%s",
-			      nick, source_p->hopcount + 1,
-			      (long) source_p->tsinfo,
-			      ubuf, source_p->username, source_p->host,
-			      user->server, source_p->info);
 	}
 	else
-		sendto_server(client_p, NULL, NOCAPS, NOCAPS,
-			      "NICK %s %d %ld %s %s %s %s :%s",
-			      nick, source_p->hopcount + 1,
-			      (long) source_p->tsinfo,
-			      ubuf, source_p->username, source_p->host,
-			      user->server, source_p->info);
+	{
+                sendto_server(client_p, NULL, NOCAPS, NOCAPS,
+                              "NICK %s %d %ld %s %s %s %s :%s",
+                              nick, source_p->hopcount + 1,
+                              (long) source_p->tsinfo,
+                              ubuf, source_p->username, source_p->host,
+                              user->server, source_p->info);
+
+		sendto_server(client_p, NULL, CAP_IPMASK, NOCAPS,
+				":%s RHOST %s :%s", me.name,
+				source_p->name, source_p->realhost);
+	}
 
 
 	return 0;
@@ -880,6 +894,48 @@
 					}
 				}
 				break;
+
+                        case 'X':
+                                if (MyConnect(source_p))
+                                {
+                                        struct ConfItem* aconf;
+                                        aconf = find_address_conf (source_p->realhost, source_p->username, &source_p->localClient->ip,
+                                                                        source_p->localClient->ip.ss_family);
+
+					ilog (L_MAIN, "hostname: %s realhost: %s", source_p->host, source_p->realhost);
+
+                                        if (IsConfDoSpoofIp(aconf))
+                                                break;
+
+                                        if (what == MODE_ADD)
+                                        {
+                                                if (has_mask(source_p))
+                                                        break;
+
+						if ((make_virthost(source_p->host, source_p->sockhost, source_p->host)) < 0)
+						{
+							source_p->umodes &= ~UMODE_IPMASK;
+							break;
+						}
+
+						source_p->umodes |= UMODE_IPMASK;
+                                        }
+
+                                        if (what == MODE_DEL)
+                                        {
+                                                if (!has_mask(source_p))
+                                                        break;
+
+						strlcpy (source_p->host, source_p->realhost, sizeof(source_p->host));
+
+						source_p->umodes &= ~UMODE_IPMASK;
+                                        }
+
+					sendto_server (NULL, NULL, CAP_IPMASK, NOCAPS, ":%s SVSHOST %s :%s", me.name, source_p->name, source_p->host);
+                                        break;
+                                }
+                                                        
+                                break;
 
 				/* we may not get these,
 				 * but they shouldnt be in default
diff -uNrd ircd-ratbox/src/version.c.SH ircd-ratbox-hostmask/src/version.c.SH
--- ircd-ratbox/src/version.c.SH	Mon Jul  7 07:26:25 2003
+++ ircd-ratbox-hostmask/src/version.c.SH	Sat Jul 31 13:03:05 2004
@@ -52,10 +52,12 @@
 #include "patchlevel.h"
 #include "serno.h"
 
+#define PATCHVER PATCHLEVEL "+ipmask-2.0.0"
+
 const char *generation = "$generation";
 const char *creation = "$creation";
 const char *platform = "$uname";
-const char *ircd_version = PATCHLEVEL;
+const char *ircd_version = PATCHVER;
 const char *serno = SERIALNUM;
 
 const char *infotext[] =
diff -uNrd ircd-ratbox/src/whowas.c ircd-ratbox-hostmask/src/whowas.c
--- ircd-ratbox/src/whowas.c	Mon Mar 15 10:58:08 2004
+++ ircd-ratbox-hostmask/src/whowas.c	Sat Jul 31 13:03:05 2004
@@ -82,6 +82,7 @@
 	strlcpy(who->name, client_p->name, sizeof(who->name));
 	strcpy(who->username, client_p->username);
 	strcpy(who->hostname, client_p->host);
+	strcpy(who->realhost, client_p->realhost);
 	strcpy(who->realname, client_p->info);
 
 	who->servername = client_p->user->server;
