Index: trunk/src/sh_cat.c
===================================================================
--- trunk/src/sh_cat.c	(revision 575)
+++ trunk/src/sh_cat.c	(revision 577)
@@ -225,4 +225,5 @@
 
   { MSG_TCP_CREG,    SH_ERR_ALL,     TCP,   N_("msg=\"Registered %s, salt %s, verifier %s\"")},
+  { MSG_TCP_AREG,    SH_ERR_ALL,     TCP,   N_("msg=\"Registered %s, hostname %s\"")},
   { MSG_TCP_FAUTH,   SH_ERR_INFO,    TCP,   N_("msg=\"Force authentication\" host=\"%s\"")},
 
@@ -569,4 +570,5 @@
 
   { MSG_TCP_CREG,    SH_ERR_ALL,     TCP,   N_("msg=<Registered %s, salt %s, verifier %s>")},
+  { MSG_TCP_AREG,    SH_ERR_ALL,     TCP,   N_("msg=<Registered %s, hostname %s>")},
   { MSG_TCP_FAUTH,   SH_ERR_INFO,    TCP,   N_("msg=<Force authentication>, client=<%s>")},
 
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 575)
+++ trunk/src/sh_readconf.c	(revision 577)
@@ -1148,4 +1148,6 @@
   { N_("setserverinterface"),  SH_SECTION_SRV,  SH_SECTION_MISC, 
     sh_xfer_set_interface },
+  { N_("alias"),               SH_SECTION_CLIENTS,           SH_SECTION_NONE, 
+    sh_xfer_register_alias },
   { N_("client"),              SH_SECTION_CLIENTS,           SH_SECTION_NONE, 
     sh_xfer_register_client },
Index: trunk/src/sh_xfer_server.c
===================================================================
--- trunk/src/sh_xfer_server.c	(revision 575)
+++ trunk/src/sh_xfer_server.c	(revision 577)
@@ -419,4 +419,9 @@
  */
 
+typedef struct client_alias {
+  char                  * alias;
+  char                  * hostname;
+} alias_t;
+
 #include "zAVLTree.h"
 
@@ -435,5 +440,5 @@
 
 /* Function to return the key for indexing
- * the argument 
+ * the argument (for the client list)
  */
 zAVLKey sh_avl_key (void const * arg)
@@ -444,4 +449,15 @@
 
 zAVLTree * all_clients = NULL;
+
+/* Function to return the key for indexing
+ * the argument (for the aliases list)
+ */
+zAVLKey sh_avl_alias (void const * arg)
+{
+  const alias_t * sa = (const alias_t *) arg;
+  return (zAVLKey) sa->alias;
+}
+
+zAVLTree * all_aliases = NULL;
 
 void sh_xfer_html_write()
@@ -470,5 +486,5 @@
 
 
-/* the destructor
+/* the destructor (client list item)
  */
 void free_client(void * inptr)
@@ -490,4 +506,98 @@
   SH_FREE(here);
   SL_RET0(_("free_client"));
+}
+
+/* the destructor (alias list item)
+ */
+void free_alias(void * inptr)
+{
+  alias_t * here;
+
+  SL_ENTER(_("free_alias"));
+  if (inptr == NULL)
+    SL_RET0(_("free_alias"));
+  else
+    here = (alias_t *) inptr;
+
+  if (here->alias != NULL)
+    SH_FREE(here->alias);
+  if (here->hostname != NULL)
+    SH_FREE(here->hostname);
+  SH_FREE(here);
+  SL_RET0(_("free_alias"));
+}
+
+int sh_xfer_register_alias (const char * str)
+{
+  alias_t    * newalias;
+  alias_t    * testalias;
+
+  const char * ptr;
+  int          sepnum  = 0;
+  int          sep     = 0;
+  register int i       = 0;
+  int          siz_str = 0;
+
+  SL_ENTER(_("sh_xfer_register_alias"));
+
+  ptr = str; 
+  while (*ptr) {
+    if (*ptr == '@' && sepnum < 1) 
+      { 
+	sep = i;
+	++sepnum;
+      } 
+    ++ptr; ++i; 
+  }
+
+  if (all_aliases == NULL)
+    {
+      all_aliases = zAVLAllocTree (sh_avl_alias, zAVL_KEY_STRING);
+      if (all_aliases == NULL) 
+	{
+	  (void) safe_logger (0, 0, NULL);
+	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	}
+    }
+
+  if ((sepnum == 1) && (sep > 0) && (i > (sep + 1)))
+    {
+      newalias                  = SH_ALLOC (sizeof(alias_t));
+      newalias->alias           = SH_ALLOC (sep+1);
+      newalias->hostname        = SH_ALLOC (sl_strlen(str)-sep);
+
+      /* truncate */
+      sl_strlcpy(newalias->alias,  &str[0],        sep+1);
+      sh_tolower(newalias->alias);
+
+      /* truncate */
+      sl_strlcpy(newalias->hostname,  &str[sep+1], sl_strlen(str)-sep);
+      sh_tolower(newalias->hostname);
+
+      testalias = (alias_t *) zAVLSearch (all_aliases, newalias->alias);
+
+      if (testalias != NULL)
+	{
+	  /* keep the alias but replace the hostname with the new one */
+	  SH_FREE(testalias->hostname);
+	  siz_str = strlen (newalias->hostname) + 1;
+	  testalias->hostname = SH_ALLOC (siz_str);
+	  sl_strlcpy(testalias->hostname, newalias->hostname, siz_str);
+	  
+	  free_alias(newalias);
+	  SL_RETURN( 0, _("sh_xfer_register_alias"));
+	}
+      else
+	{
+	  if (0 == zAVLInsert (all_aliases, newalias))
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AREG,
+			      newalias->alias, 
+			      newalias->hostname);
+	      SL_RETURN( 0, _("sh_xfer_register_alias"));
+	    }
+	}
+    }
+  SL_RETURN (-1, _("sh_xfer_register_alias"));
 }
 
@@ -1053,4 +1163,5 @@
 client_t * search_register(sh_conn_t * conn, int pos)
 {
+  alias_t  * this_alias;
   client_t * this_client;
   char       peer_ip[SH_IP_BUF];
@@ -1086,4 +1197,12 @@
 	{
 	  sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1);
+	}
+      else
+	{
+	  this_alias = zAVLSearch(all_aliases, peer_name);
+	  if (this_alias)
+	    {
+	      sl_strlcpy(peer_name, this_alias->hostname, MAXHOSTNAMELEN + 1);
+	    }
 	}
 
@@ -3375,4 +3494,8 @@
 	    sh_xfer_mark_dead ();
 
+	    /* free the aliases list */
+	    zAVLFreeTree (all_aliases, free_alias);
+	    all_aliases = NULL;
+
 	    reset_count_dev_console();
 	    reset_count_dev_time();
