diff -ruN ../orig/ircd-hybrid/contrib/m_operspy.c ircd-hybrid/contrib/m_operspy.c
--- ../orig/ircd-hybrid/contrib/m_operspy.c	2004-07-08 00:27:16.000000000 +0000
+++ ircd-hybrid/contrib/m_operspy.c	2004-07-20 06:10:20.627582952 +0000
@@ -446,7 +446,7 @@
 
     sendto_one(client_p, form_str(RPL_WHOISUSER), me.name,
                client_p->name, target_p->name, target_p->username,
-               target_p->host, target_p->info);
+               target_p->orighost, target_p->info);
     ircsprintf(buf, form_str(RPL_WHOISCHANNELS), me.name,
                client_p->name, target_p->name, "");
 
diff -ruN ../orig/ircd-hybrid/include/client.h ircd-hybrid/include/client.h
--- ../orig/ircd-hybrid/include/client.h	2004-02-24 03:36:18.000000000 +0000
+++ ircd-hybrid/include/client.h	2004-07-20 04:56:06.577701456 +0000
@@ -58,6 +58,7 @@
   char*          away;      /* pointer to away message */
   time_t         last_away; /* Away since... */
   time_t         last;
+  time_t         svs_stamp; /* services timestamp */
   struct Client *server;    /* pointer to server */
   char*          response;  /* expected response from client */
   char*          auth_oper; /* Operator to become if they supply the response.*/
@@ -154,6 +155,8 @@
    * considered a read-only field after the client has registered.
    */
   char              host[HOSTLEN + 1];     /* client's hostname */
+  char              orighost[HOSTLEN + 1]; /* client's hostname, only used if spoofed. */
+
   /*
    * client->info for unix clients will normally contain the info from the 
    * gcos field in /etc/passwd but anything can go here.
@@ -393,6 +396,11 @@
 /* user information flags, only settable by remote mode or local oper */
 #define UMODE_OPER         0x10000 /* Operator */
 #define UMODE_ADMIN        0x20000 /* Admin on server */
+
+/* going back to a settable flag */
+#define UMODE_VHOST        0x40000 /* vhosted user */
+#define UMODE_IDENTIFIED   0x80000 /* Identified to Services */
+
 #define UMODE_ALL	   UMODE_SERVNOTICE
 
 #define SEND_UMODES  (UMODE_INVISIBLE | UMODE_OPER | UMODE_WALLOP | \
@@ -463,6 +471,8 @@
 #define IsInvisible(x)          ((x)->umodes & UMODE_INVISIBLE)
 #define SendWallops(x)          ((x)->umodes & UMODE_WALLOP)
 #define IsSetCallerId(x)	((x)->umodes & UMODE_CALLERID)
+#define IsVhost(x)                            ((x)->umodes & UMODE_VHOST)
+#define IsIdentified(x)			((x)->umodes & UMODE_IDENTIFIED)
 
 #define SetSendQExceeded(x)	((x)->flags |= FLAGS_SENDQEX)
 #define IsSendQExceeded(x)	((x)->flags &  FLAGS_SENDQEX)
diff -ruN ../orig/ircd-hybrid/modules/Makefile.in ircd-hybrid/modules/Makefile.in
--- ../orig/ircd-hybrid/modules/Makefile.in	2003-09-29 19:05:51.000000000 +0000
+++ ircd-hybrid/modules/Makefile.in	2004-07-20 04:56:06.578701304 +0000
@@ -53,6 +53,8 @@
   m_away.c \
   m_capab.c \
   m_cburst.c \
+  m_chghost.c \
+  m_chgident.c \
   m_close.c \
   @SSL_SRCS_ENABLE@ \
   m_connect.c \
@@ -85,8 +87,10 @@
   m_restart.c \
   m_resv.c \
   m_set.c \
+  m_services.c \
   m_stats.c \
   m_svinfo.c \
+  m_svsmode.c \
   m_testline.c \
   m_time.c \
   m_topic.c \
diff -ruN ../orig/ircd-hybrid/modules/core/m_nick.c ircd-hybrid/modules/core/m_nick.c
--- ../orig/ircd-hybrid/modules/core/m_nick.c	2004-07-08 00:27:30.000000000 +0000
+++ ircd-hybrid/modules/core/m_nick.c	2004-07-20 04:56:06.578701304 +0000
@@ -756,6 +756,8 @@
 
   strcpy(source_p->name, nick);
   hash_add_client(source_p);
+  
+  source_p->umodes &= UMODE_IDENTIFIED;
 
   /* remove all accepts pointing to the client */
   del_all_accepts(source_p);
diff -ruN ../orig/ircd-hybrid/modules/m_chghost.c ircd-hybrid/modules/m_chghost.c
--- ../orig/ircd-hybrid/modules/m_chghost.c	1970-01-01 00:00:00.000000000 +0000
+++ ircd-hybrid/modules/m_chghost.c	2004-07-20 04:56:06.579701152 +0000
@@ -0,0 +1,99 @@
+/***************************************************************************
+                           m_chghost.c
+                           -------------------
+    copyright            : (C) 2002 by Martin Scholl
+    email                : ms@deridiot.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "stdinc.h"
+#include "tools.h"
+#include "channel.h"
+#include "client.h"
+#include "common.h"
+#include "irc_string.h"
+#include "ircd.h"
+#include "hostmask.h"
+#include "numeric.h"
+#include "fdlist.h"
+#include "s_bsd.h"
+#include "s_conf.h"
+#include "s_log.h"
+#include "s_misc.h"
+#include "send.h"
+#include "hash.h"
+#include "handlers.h"
+#include "s_serv.h"
+#include "msg.h"
+#include "parse.h"
+#include "modules.h"
+#include "whowas.h"
+
+static void ms_chghost( struct Client *client_p, struct Client *source_p,
+			int parc, char *parv[] );
+
+struct Message chghost_msgtab = {
+  "CHGHOST", 0, 3, 3, 0, MFLG_SLOW, 0,
+  /* uncomment this if you use beta 9 hybird ircd */
+  /*   "CHGHOST", 0, 3, 3, MFLG_SLOW, 0 */
+  { m_ignore, m_ignore, ms_chghost, m_ignore, m_ignore, m_ignore }
+};
+
+void _modinit(void) 
+{
+  mod_add_cmd(&chghost_msgtab);
+}
+
+void _moddeinit(void)
+{
+  mod_del_cmd(&chghost_msgtab);
+}
+
+char *_version = "20020401";
+
+static void ms_chghost(struct Client *client_p, struct Client *source_p,
+                    int parc, char *parv[])
+{
+  struct Client *target=NULL;
+  dlink_node    *ptr       = NULL;
+  struct Client *bclient_p = NULL;
+  
+  if( IsServer( source_p ) && MyConnect( source_p ) )
+    {
+      /* this is the version for beta 7 servers */
+/*       if( !(target = find_client( parv[1], NULL ) ) ) { */
+      if( (target = find_person( parv[1] ) ) == NULL ) {
+	/* 
+	 * chasing client now 
+	 * dont know which timeout to use... *shame*
+	 */
+        if ((target = get_history(parv[1], (time_t)ConfigFileEntry.kill_chase_time_limit)) == NULL)
+	  {
+	    sendto_one( client_p, form_str( ERR_NOSUCHNICK ),
+			me.name, parv[0], parv[1] );
+	    return;
+	  }
+      }
+
+      if( !strcmp( target->host, parv[2] ) ) return;
+      
+      strcpy( target->host, parv[2] );
+      
+      for( ptr = serv_list.head; ptr; ptr = ptr->next ) 
+	{
+	  bclient_p = ptr->data;
+	  if( bclient_p == source_p ) continue;
+	  
+	  sendto_one( bclient_p, ":%s CHGHOST %s %s", me.name, parv[1],
+		      target->host );
+	}
+    }
+}
diff -ruN ../orig/ircd-hybrid/modules/m_chgident.c ircd-hybrid/modules/m_chgident.c
--- ../orig/ircd-hybrid/modules/m_chgident.c	1970-01-01 00:00:00.000000000 +0000
+++ ircd-hybrid/modules/m_chgident.c	2004-07-20 04:56:06.580701000 +0000
@@ -0,0 +1,108 @@
+/***************************************************************************
+                           m_chgident.c
+                           -------------------
+    copyright            : (C) 2001 by Martin Scholl
+    email                : ms@deridiot.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "stdinc.h"
+#include "tools.h"
+#include "channel.h"
+#include "client.h"
+#include "common.h"
+#include "irc_string.h"
+#include "ircd.h"
+#include "hostmask.h"
+#include "numeric.h"
+#include "fdlist.h"
+#include "s_bsd.h"
+#include "s_conf.h"
+#include "s_log.h"
+#include "s_misc.h"
+#include "send.h"
+#include "hash.h"
+#include "handlers.h"
+#include "s_serv.h"
+#include "msg.h"
+#include "parse.h"
+#include "modules.h"
+#include "whowas.h"
+
+
+static void ms_chgident( struct Client *client_p, struct Client *source_p,
+			 int part, char *parv[]);
+
+struct Message chgident_msgtab = {
+  "CHGIDENT", 0, 3, 3, 0, 0, 0,
+  /*   "CHGIDENT", 0, 3, 3, MFLG_SLOW, */ /* <- old line for hybrid 7-beta7 servers */
+  { m_ignore, m_ignore, ms_chgident, m_ignore, m_ignore, m_ignore }
+};
+
+char * _version = "20020401";
+
+void _modinit( void )
+{
+  mod_add_cmd(&chgident_msgtab);
+}
+
+void _moddeinit( void )
+{
+  mod_del_cmd(&chgident_msgtab);
+}
+
+/*
+ * The incoming message has been send from an 'average' user and not
+ * a server. Because only servers are permitted to reach command
+ * 'CHGIDENT' through this module average users / irc operators cannot
+ * reach CHGIDENT command
+ */
+static void ms_chgident( struct Client *client_p, struct Client *source_p,
+			int parc, char *parv[])
+{
+  struct Client *target    = NULL;
+  dlink_node    *ptr       = NULL;
+  struct Client *bclient_p = NULL;
+
+  if( IsServer( source_p ) ) 
+    {
+      /*       if( !(target = find_client( parv[1], NULL ) ) ) { */ /* this is the old version for beta 7 servers */
+      if( (target = find_person( parv[1] ) ) == NULL ) { /* this is the version for beta  9 hybrid servers */
+	/* 
+	 * chasing client now 
+	 * dont know which timeout to use... *shame*
+	 */
+	if( !(target = get_history( parv[1], (time_t)ConfigFileEntry.kill_chase_time_limit))  ) 
+	  {
+	    ms_error( client_p, source_p, parc, parv );
+	    
+ 	    sendto_one( client_p, form_str( ERR_NOSUCHNICK ),
+ 			me.name, parv[0], parv[1] );
+	    return;
+	  }
+      }
+
+      if( strcmp( target->username, parv[2] ) ) {
+	strcpy( & ( target->username[0] ), parv[2] );
+	
+	
+	for( ptr = serv_list.head; ptr; ptr = ptr->next ) 
+	  {
+	    bclient_p = ptr->data;
+	  if( bclient_p == source_p ) continue;
+	  
+	  sendto_one( bclient_p, ":%s CHGIDENT %s %s", source_p->name, 
+		      parv[1],
+		      target->username );
+	  }
+      }
+    }
+}
diff -ruN ../orig/ircd-hybrid/modules/m_services.c ircd-hybrid/modules/m_services.c
--- ../orig/ircd-hybrid/modules/m_services.c	1970-01-01 00:00:00.000000000 +0000
+++ ircd-hybrid/modules/m_services.c	2004-07-20 04:56:06.598698264 +0000
@@ -0,0 +1,341 @@
+/*
+ *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ *  m_services.c: Services functions.
+ *
+ *  Copyright (C) 2004 by the past and present ircd coders, and others.
+ *
+ *  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: m_services.c,v 1.12 2004/06/17 12:36:06 jon Exp $
+ */
+/*
+ * trivial modifications by dougk_ff7 to add support for anope services for occn, as well
+ * as fixing a few bugs...
+ */
+
+#include "stdinc.h"
+#include "handlers.h"
+#include "channel.h"
+#include "channel_mode.h"
+#include "client.h"
+#include "common.h"
+#include "ircd.h"
+#include "irc_string.h"
+#include "numeric.h"
+#include "fdlist.h"
+#include "s_bsd.h"
+#include "s_conf.h"
+#include "s_log.h"
+#include "s_serv.h"
+#include "s_user.h"
+#include "send.h"
+#include "list.h"
+#include "msg.h"
+#include "parse.h"
+#include "modules.h"
+#include "hash.h"
+#include "resv.h"
+#include "packet.h"
+
+#define OPERSERV "OperServ"
+#define HOSTSERV "HostServ"
+#define NICKSERV "NickServ"
+#define HELPSERV "HelpServ"
+#define CHANSERV "ChanServ"
+#define MEMOSERV "MemoServ"
+#define SERVICES_NAME "services."
+
+char *reconstruct_parv(int parc, char *parv[]);
+
+static void m_operserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+static void m_hostserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+static void m_nickserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+static void m_helpserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+static void m_chanserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+static void m_memoserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+static void m_identify(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
+
+struct Message operserv_msgtab = {
+  "OPERSERV", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_operserv, m_ignore, m_ignore, m_operserv, m_ignore}
+};
+
+struct Message hostserv_msgtab = {
+  "HOSTSERV", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_hostserv, m_ignore, m_ignore, m_hostserv, m_ignore}
+};
+
+struct Message nickserv_msgtab = {
+  "NICKSERV", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_nickserv, m_ignore, m_ignore, m_nickserv, m_ignore}
+};
+
+struct Message helpserv_msgtab = {
+  "HELPSERV", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_helpserv, m_ignore, m_ignore, m_helpserv, m_ignore}
+};
+
+struct Message chanserv_msgtab = {
+  "CHANSERV", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_chanserv, m_ignore, m_ignore, m_chanserv, m_ignore}
+};
+
+struct Message memoserv_msgtab = {
+  "MEMOSERV", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_memoserv, m_ignore, m_ignore, m_memoserv, m_ignore}
+};
+
+struct Message os_msgtab = {
+  "OS", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_operserv, m_ignore, m_ignore, m_operserv, m_ignore}
+};
+
+struct Message ns_msgtab = {
+  "NS", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_nickserv, m_ignore, m_ignore, m_nickserv, m_ignore}
+};
+
+struct Message hs_msgtab = {
+  "HS", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_helpserv, m_ignore, m_ignore, m_helpserv, m_ignore}
+};
+
+struct Message cs_msgtab = {
+  "CS", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_chanserv, m_ignore, m_ignore, m_chanserv, m_ignore}
+};
+
+struct Message ms_msgtab = {
+  "MS", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_memoserv, m_ignore, m_ignore, m_memoserv, m_ignore}
+};
+
+struct Message identify_msgtab = {
+  "IDENTIFY", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_identify, m_ignore, m_ignore, m_identify, m_ignore}
+};
+
+#ifndef STATIC_MODULES
+void _modinit(void)
+{
+  mod_add_cmd(&operserv_msgtab);
+  mod_add_cmd(&hostserv_msgtab);
+  mod_add_cmd(&nickserv_msgtab);
+  mod_add_cmd(&helpserv_msgtab);
+  mod_add_cmd(&chanserv_msgtab);
+  mod_add_cmd(&memoserv_msgtab);
+  mod_add_cmd(&os_msgtab);
+  mod_add_cmd(&ns_msgtab);
+  mod_add_cmd(&hs_msgtab);
+  mod_add_cmd(&cs_msgtab);
+  mod_add_cmd(&ms_msgtab);
+  mod_add_cmd(&identify_msgtab);
+}
+
+void _moddeinit(void)
+{
+  mod_del_cmd(&operserv_msgtab);
+  mod_del_cmd(&hostserv_msgtab);
+  mod_del_cmd(&nickserv_msgtab);
+  mod_del_cmd(&helpserv_msgtab);
+  mod_del_cmd(&chanserv_msgtab);
+  mod_del_cmd(&memoserv_msgtab);
+  mod_del_cmd(&os_msgtab);
+  mod_del_cmd(&ns_msgtab);
+  mod_del_cmd(&hs_msgtab);
+  mod_del_cmd(&cs_msgtab);
+  mod_del_cmd(&ms_msgtab);
+  mod_del_cmd(&identify_msgtab);
+}
+const char *_version = "$Revision: 1.12-occn $";
+#endif
+
+char *reconstruct_parv(int parc, char *parv[])
+{
+  static char tmpbuf[BUFSIZE]; int i;
+
+  strlcpy(tmpbuf, parv[0], BUFSIZE);
+  for (i = 1; i < parc; i++)
+  {
+    strlcat(tmpbuf, " ", BUFSIZE);
+    strlcat(tmpbuf, parv[i], BUFSIZE);
+  }
+  return tmpbuf;
+}
+
+static void m_operserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
+{
+  struct Client *target_p;
+
+  if (parv[1] == NULL)
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+
+  if ((target_p = find_server(SERVICES_NAME)))
+  {
+    sendto_one(target_p, ":%s PRIVMSG %s@%s :%s", parv[0], OPERSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+  }
+  else
+  {
+    sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, OPERSERV);
+  }
+}
+
+static void m_hostserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
+{
+  struct Client *target_p;
+
+  if (parv[1] == NULL)
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+
+  if ((target_p = find_server(SERVICES_NAME)))
+  {
+    sendto_one(target_p, ":%s PRIVMSG %s@%s :%s", parv[0], HOSTSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+  }
+  else
+  {
+    sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, HOSTSERV);
+  }
+}
+
+static void m_nickserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
+{
+  struct Client *target_p;
+
+  if (parv[1] == NULL)
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+
+  if ((target_p = find_server(SERVICES_NAME)))
+  {
+    sendto_one(target_p, ":%s PRIVMSG %s@%s :%s", parv[0], NICKSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+  }
+  else
+  {
+    sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, NICKSERV);
+  }
+}
+
+static void m_helpserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
+{
+  struct Client *target_p;
+
+  if (parv[1] == NULL)
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+
+  if ((target_p = find_server(SERVICES_NAME)))
+  {
+    sendto_one(target_p, ":%s PRIVMSG %s@%s :%s", parv[0], HELPSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+  }
+  else
+  {
+    sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, HELPSERV);
+  }
+}
+
+static void m_chanserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
+{
+  struct Client *target_p;
+
+  if (parv[1] == NULL)
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+
+  if ((target_p = find_server(SERVICES_NAME)))
+  {
+    sendto_one(target_p, ":%s PRIVMSG %s@%s :%s", parv[0], CHANSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+  }
+  else
+  {
+    sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, CHANSERV);
+  }
+}
+
+static void m_memoserv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
+{
+  struct Client *target_p;
+
+  if (parv[1] == NULL)
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+
+  if ((target_p = find_server(SERVICES_NAME)))
+  {
+    sendto_one(target_p, ":%s PRIVMSG %s@%s :%s", parv[0], MEMOSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+  }
+  else
+  {
+    sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, MEMOSERV);
+  }
+}
+
+/*
+ * m_identify
+ *      parv[0] = sender prefix
+ *      parv[1] = nickname/channel
+ *      parv[2] = data to send to nickserv/chanserv
+ */
+static void 
+m_identify(struct Client *client_p, struct Client *source_p,
+	   int parc, char *parv[])
+{
+  struct Client *target_p;
+ 
+  if(parc < 2 || EmptyString(parv[1]))
+  {
+    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
+    return;
+  }
+  if(*parv[1] == '#')
+  {
+    if ((target_p = find_server(SERVICES_NAME)))
+    {
+      sendto_one(target_p, ":%s PRIVMSG %s@%s :IDENTIFY %s",
+                 CHANSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+    }
+    else
+    {
+      sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, CHANSERV);
+    }
+  }
+  else
+  {
+    if ((target_p = find_server(SERVICES_NAME)))
+    {
+      sendto_one(target_p, ":%s PRIVMSG %s@%s :IDENTIFY %s",
+		 parv[0], NICKSERV, SERVICES_NAME, reconstruct_parv(parc - 1, &parv[1]));
+    }
+    else
+    {
+      sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, NICKSERV);
+    }
+  }
+}
+
diff -ruN ../orig/ircd-hybrid/modules/m_svsmode.c ircd-hybrid/modules/m_svsmode.c
--- ../orig/ircd-hybrid/modules/m_svsmode.c	1970-01-01 00:00:00.000000000 +0000
+++ ircd-hybrid/modules/m_svsmode.c	2004-07-20 05:58:00.290131352 +0000
@@ -0,0 +1,171 @@
+/*
+ *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ *  m_svsmode.c: Sets a user or channel mode.
+ *
+ *  Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ *  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: m_svsmode.c,v 1.8 2002/08/27 22:04:00 strtok Exp $
+ */
+
+#include "stdinc.h"
+#include "tools.h"
+#include "handlers.h"
+#include "channel.h"
+#include "channel_mode.h"
+#include "client.h"
+#include "hash.h"
+#include "irc_string.h"
+#include "ircd.h"
+#include "numeric.h"
+#include "s_user.h"
+#include "s_conf.h"
+#include "s_serv.h"
+#include "send.h"
+#include "msg.h"
+#include "parse.h"
+#include "modules.h"
+#include "packet.h"
+#include "common.h"
+
+extern BlockHeap *ban_heap;
+
+static void m_svsmode(struct Client*, struct Client*, int, char**);
+
+struct Message mode_msgtab = {
+  "SVSMODE", 0, 0, 2, 0, MFLG_SLOW, 0,
+  {m_unregistered, m_ignore, m_svsmode, m_ignore, m_ignore, m_ignore}
+};
+#ifndef STATIC_MODULES
+
+void
+_modinit(void)
+{
+  mod_add_cmd(&mode_msgtab);
+}
+
+void
+_moddeinit(void)
+{
+  mod_del_cmd(&mode_msgtab);
+}
+
+
+const char *_version = "$Revision: 1.8 $";
+#endif
+/*
+ * m_svsmode - SVSMODE command handler
+ * parv[0] - sender
+ * parv[1] - channel
+ * parv[2] - modes
+ * parv[3] - nick (depending on modes)
+ * parv[4] - nickts (depending on modes)
+ *
+ * parv[0] - sender
+ * parv[1] - user
+ * parv[2] - modes
+ */
+static void m_svsmode(struct Client *client_p, struct Client *source_p,
+              int parc, char *parv[])
+{
+
+  struct Client *target_p;
+  int badflag = NO;
+  int what, svs_stamp;
+  char **p, *m;
+  static char ubuf[12];
+  dlink_node    *ptr       = NULL;  
+
+  what = MODE_ADD;
+  
+  if (parc < 3)
+  {
+      sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
+                 me.name, parv[0], "SVSMODE");
+      return;
+  }
+
+  if (parv[1][0] == '#')
+  {
+     return;
+  }
+
+  if ((target_p = find_person(parv[1])) == NULL)
+  {
+      if (MyConnect(source_p))
+        sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
+                   me.name, parv[0], parv[1]);
+      return;
+  }
+
+  for(p = &parv[2]; p && *p; p++)
+     for(m = *p; *m; m++)
+        switch(*m)
+        {
+           case '+':
+              what = MODE_ADD;
+              break;
+           case '-':
+              what = MODE_DEL;
+               break;
+           case 'h':
+		/* borrowing PleXusIRCd's hostmasking... with changes.
+		 * -dougk_ff7
+		 */
+                 if (what == MODE_ADD) {
+                        if (IsVhost(target_p)) break;
+                        target_p->umodes |= UMODE_VHOST;
+
+                        if (!MyConnect(target_p)) break;
+  
+                        		strncpy(target_p->orighost, target_p->host, HOSTLEN);
+                                make_virthost(target_p->host, target_p->localClient->sockhost, target_p->host);
+				for( ptr = serv_list.head; ptr; ptr = ptr->next ) {
+					sendto_one( ptr->data, ":%s CHGHOST %s %s", me.name, target_p->name, target_p->host );
+				}
+                } else {
+                        target_p->umodes &= ~UMODE_VHOST;
+                        strncpy(target_p->host, target_p->orighost, HOSTLEN);
+                }
+                send_umode(target_p, target_p, 0, SEND_UMODES, ubuf);
+                break;
+           case 'r':
+           case 'd':
+              if(what == MODE_ADD)
+              {
+                 if(parc >= 4)
+                 {
+                    svs_stamp = atoi(parv[3]);
+                    target_p->user->svs_stamp = svs_stamp;
+                 }
+                 else
+                    target_p->umodes |= UMODE_IDENTIFIED;
+                   
+              }
+              else
+              {
+                 target_p->umodes &= ~UMODE_IDENTIFIED;
+              }
+              break;
+        }
+  /* Propogate the SVSMODE to other servers */
+  sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS, NOFLAGS,
+                 ":%s SVSMODE %s %s %s", source_p->name, target_p->name,
+                  parv[2], (parc >= 4) ? parv[3] : "");
+}
+
+
diff -ruN ../orig/ircd-hybrid/src/Makefile.in ircd-hybrid/src/Makefile.in
--- ../orig/ircd-hybrid/src/Makefile.in	2004-01-23 00:46:43.000000000 +0000
+++ ircd-hybrid/src/Makefile.in	2004-07-20 04:56:06.600697960 +0000
@@ -62,6 +62,7 @@
  channel_mode.c \
  client.c \
  cluster.c \
+ cloak.c \
  @CRYPT_C@ \
  dbuf.c	\
  event.c \
diff -ruN ../orig/ircd-hybrid/src/client.c ircd-hybrid/src/client.c
--- ../orig/ircd-hybrid/src/client.c	2004-04-01 02:53:24.000000000 +0000
+++ ircd-hybrid/src/client.c	2004-07-20 04:56:06.601697808 +0000
@@ -1592,6 +1592,8 @@
   strcpy(source_p->name, nick);
   hash_add_client(source_p);
 
+  source_p->umodes &= UMODE_IDENTIFIED;
+
   /* Make sure everyone that has this client on its accept list
    * loses that reference. 
    */
diff -ruN ../orig/ircd-hybrid/src/cloak.c ircd-hybrid/src/cloak.c
--- ../orig/ircd-hybrid/src/cloak.c	1970-01-01 00:00:00.000000000 +0000
+++ ircd-hybrid/src/cloak.c	2004-07-20 04:56:06.602697656 +0000
@@ -0,0 +1,280 @@
+/*
+ *  cloak.c: Provides Hostname Cloaking
+ *
+ *  Copyright (C) 2000-2002 Edward Brocklesby, Hybrid 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 $
+ */
+/*
+**
+** Originally rewritten from AustNet's VirtualWorld Code.
+** Virtual World written by Roger 'RogerY' Yerramsetti <rogery@austnet.org>
+**
+** Rewritten using the crc32 implementation by //ylo based on the original
+** implementation by Gary S. Brown
+**
+** hiddenhost implementation based on the code from UnrealIRCd by
+** RaYmAn, NiQuiL, narf, Griever (great thinking) eternal, bball, JK.@ roxnet.org
+**
+** Additional ideas and code by ShadowMaster, [-Th3Dud3-] (RageIRCd) and Solaris @ Demonkarma.net
+**
+*/
+
+/* backporting this from PleXusIRCd, just to plain old hyb7, using a few different 
+ * things along the way
+ * -dougk_ff7
+ */
+
+
+
+#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"
+
+#define KEY 23857
+#define KEY2 38447
+#define KEY3 64709
+
+int str2arr (char **, char *, char *);
+unsigned long crc32 (const unsigned char *s, unsigned int len);
+
+
+ /* The implementation here was originally done by Gary S. Brown.  I have
+    borrowed the tables directly, and made some minor changes to the
+    crc32-function (including changing the interface). //ylo */
+
+  /* ============================================================= */
+  /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or       */
+  /*  code or tables extracted from it, as desired without restriction.     */
+  /*                                                                        */
+  /*  First, the polynomial itself and its table of feedback terms.  The    */
+  /*  polynomial is                                                         */
+  /*  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0   */
+  /*                                                                        */
+  /*  Note that we take it "backwards" and put the highest-order term in    */
+  /*  the lowest-order bit.  The X^32 term is "implied"; the LSB is the     */
+  /*  X^31 term, etc.  The X^0 term (usually shown as "+1") results in      */
+  /*  the MSB being 1.                                                      */
+  /*                                                                        */
+  /*  Note that the usual hardware shift register implementation, which     */
+  /*  is what we're using (we're merely optimizing it by doing eight-bit    */
+  /*  chunks at a time) shifts bits into the lowest-order term.  In our     */
+  /*  implementation, that means shifting towards the right.  Why do we     */
+  /*  do it this way?  Because the calculated CRC must be transmitted in    */
+  /*  order from highest-order term to lowest-order term.  UARTs transmit   */
+  /*  characters in order from LSB to MSB.  By storing the CRC this way,    */
+  /*  we hand it to the UART in the order low-byte to high-byte; the UART   */
+  /*  sends each low-bit to hight-bit; and the result is transmission bit   */
+  /*  by bit from highest- to lowest-order term without requiring any bit   */
+  /*  shuffling on our part.  Reception works similarly.                    */
+  /*                                                                        */
+  /*  The feedback terms table consists of 256, 32-bit entries.  Notes:     */
+  /*                                                                        */
+  /*      The table can be generated at runtime if desired; code to do so   */
+  /*      is shown later.  It might not be obvious, but the feedback        */
+  /*      terms simply represent the results of eight shift/xor opera-      */
+  /*      tions for all combinations of data and CRC register values.       */
+  /*                                                                        */
+  /*      The values must be right-shifted by eight bits by the "updcrc"    */
+  /*      logic; the shift must be unsigned (bring in zeroes).  On some     */
+  /*      hardware you could probably optimize the shift in assembler by    */
+  /*      using byte-swap instructions.                                     */
+  /*      polynomial $edb88320                                              */
+  /*                                                                        */
+  /*  --------------------------------------------------------------------  */
+
+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
+};
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+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;
+}
+
+
+
+/* Regular user host */
+void
+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];
+  unsigned long masked[8];
+
+  /* Paranoia. curr & host are pointers */
+  strncpy (s2, curr, HOSTLEN);
+  strncpy (s, host, HOSTLEN);
+
+  parc = str2arr (parv, s, ".");
+  parc2 = str2arr (parv2, s2, ".");
+
+
+
+  /* crc32 and hashing using our 3 keys */
+  hash[0] = ((crc32 (parv[3], strlen (parv[3])) + KEY2) ^ KEY) ^ KEY3;
+  hash[1] = ((crc32 (parv[2], strlen (parv[2])) + KEY2) ^ KEY) ^ KEY3;
+
+
+  /* Why make life easy on crackers? Bitshifting */
+  hash[0] <<= 2;
+  hash[0] >>= 2;
+
+  hash[1] <<= 2;
+  hash[1] >>= 2;
+
+  /* Check if host could be IPv4 */
+  if (parc2 == 4 || parc2 < 2)
+    {
+      len = strlen (parv2[3]);
+      /* Check if its an IPv4 for sure */
+      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;
+
+	  ircsprintf (mask, "%lx.%lx.%lx.%lx.IP",
+		      hash[0], hash[1], hash[2], hash[3]);
+	}
+      else
+	{
+	  ircsprintf (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)		/* There are isp's like *.isp.co.uk etc out there */
+	{
+	  ircsprintf (mask, "%s-%lx.%lx.%s.%s.%s",
+		      ServerInfo.network_name, hash[0], hash[1], parv2[parc2 - 3], parv2[parc2 - 2],
+		      parv2[parc2 - 1]);
+	}
+      else
+	{
+	  ircsprintf (mask, "%s-%lx.%lx.%s.%s",
+		      ServerInfo.network_name, hash[0], hash[1], parv2[parc2 - 2], parv2[parc2 - 1]);
+	}
+    }
+  strncpy (new, mask, HOSTLEN);
+  return;
+}
diff -ruN ../orig/ircd-hybrid/src/s_user.c ircd-hybrid/src/s_user.c
--- ../orig/ircd-hybrid/src/s_user.c	2003-12-31 01:54:14.000000000 +0000
+++ ircd-hybrid/src/s_user.c	2004-07-20 05:11:30.727209376 +0000
@@ -76,8 +76,10 @@
   { UMODE_BOTS,       'b' },
   { UMODE_CCONN,      'c' },
   { UMODE_DEBUG,      'd' },
+  { UMODE_IDENTIFIED, 'e' },
   { UMODE_FULL,       'f' },
   { UMODE_CALLERID,   'g' },
+  { UMODE_VHOST,      'h' },
   { UMODE_INVISIBLE,  'i' },
   { UMODE_SKILL,      'k' },
   { UMODE_LOCOPS,     'l' },
@@ -133,10 +135,10 @@
   UMODE_BOTS,       /* b */
   UMODE_CCONN,      /* c */
   UMODE_DEBUG,      /* d */
-  0,                /* e */
+  UMODE_IDENTIFIED, /* e */
   UMODE_FULL,       /* f */
   UMODE_CALLERID,   /* g */
-  0,                /* h */
+  UMODE_VHOST,      /* h */
   UMODE_INVISIBLE,  /* i */
   0,                /* j */
   UMODE_SKILL,      /* k */
@@ -957,6 +959,7 @@
   int what = MODE_ADD;
   int badflag = 0; /* Only send one bad flag notice */
   char buf[BUFSIZE];
+  dlink_node    *ptr       = NULL;  
 #if 0
   /* already covered by m_mode */
   if (parc < 2)
@@ -1056,7 +1059,58 @@
           }
 
           break;
+        case 'e':
+          /* local clients may NEVER change this mode */
+          if (what == MODE_ADD)
+          {
+            if (IsServer(client_p))
+              source_p->umodes |= UMODE_IDENTIFIED;
+            else
+              break;
+          }
+          else
+          {
+            if (IsServer(client_p))
+              source_p->umodes &= UMODE_IDENTIFIED;
+            else
+              break;
+          }
+          
+          break;
 
+		/* borrowing PleXusIRCd's hostmasking... with changes.
+		 * -dougk_ff7
+		 */
+		case 'h' :
+                 if (what == MODE_ADD) {
+                        /* if they are already hidden, don't hide them again
+                         * of they are not a local client
+                         * note: this will b0rk if the user happens to have a hostserv mask, too.
+                         * possible fix? ensure hostserv sets +h first (anope patch)
+                         */
+                        if (IsVhost(target_p)) break;
+  
+                        target_p->umodes |= UMODE_VHOST;
+                        if (MyClient(target_p)) {
+                        	strncpy(target_p->orighost, target_p->host, HOSTLEN);
+                                make_virthost(target_p->host, target_p->localClient->sockhost, target_p->host);
+				for( ptr = serv_list.head; ptr; ptr = ptr->next ) {
+					sendto_one( ptr->data, ":%s CHGHOST %s %s", me.name, target_p->name, target_p->host );
+				}
+	                        sendto_one(target_p, "NOTICE %s :*** Your host is masked (%s).", me.name, target_p->host);
+                        }
+                } else {
+                        target_p->umodes &= ~UMODE_VHOST;
+                        if (MyClient(target_p)) {
+	                        strncpy(target_p->host, target_p->orighost, HOSTLEN);
+				for( ptr = serv_list.head; ptr; ptr = ptr->next ) {
+					sendto_one( ptr->data, ":%s CHGHOST %s %s", me.name, target_p->name, target_p->host );
+				}
+	                        sendto_one(target_p, "NOTICE %s :*** Host masking disabled. (%s)", me.name, target_p->orighost);
+			}
+                }
+                break;
+			
         /* we may not get these,
          * but they shouldnt be in default
          */
