viced: Abstract out peer mapping code
[openafs.git] / src / viced / host.c
index c1b8da9..2d80f43 100644 (file)
@@ -32,9 +32,6 @@
 #include <afs/ihandle.h>
 #include <afs/vnode.h>
 #include <afs/volume.h>
-#ifdef AFS_ATHENA_STDENV
-#include <krb.h>
-#endif
 #include <afs/acl.h>
 #include <afs/ptclient.h>
 #include <afs/ptuser.h>
 #include "callback.h"
 #ifdef AFS_DEMAND_ATTACH_FS
 #include "../util/afsutil_prototypes.h"
-#include "../tviced/serialize_state.h"
+#include "serialize_state.h"
 #endif /* AFS_DEMAND_ATTACH_FS */
 
-#ifdef AFS_PTHREAD_ENV
 pthread_mutex_t host_glock_mutex;
-#endif /* AFS_PTHREAD_ENV */
 
 extern int Console;
 extern int CurrentConnections;
@@ -115,7 +110,7 @@ GetCEBlock(void)
     struct CEBlock *block;
     int i;
 
-    block = (struct CEBlock *)malloc(sizeof(struct CEBlock));
+    block = malloc(sizeof(struct CEBlock));
     if (!block) {
        ViceLog(0, ("Failed malloc in GetCEBlock\n"));
        ShutDownAndCore(PANIC);
@@ -203,15 +198,13 @@ GetHTBlock(void)
        return;
     }
 
-    block = (struct HTBlock *)malloc(sizeof(struct HTBlock));
+    block = malloc(sizeof(struct HTBlock));
     if (!block) {
        ViceLog(0, ("Failed malloc in GetHTBlock\n"));
        ShutDownAndCore(PANIC);
     }
-#ifdef AFS_PTHREAD_ENV
     for (i = 0; i < (h_HTSPERBLOCK); i++)
        CV_INIT(&block->entry[i].cond, "block entry", CV_DEFAULT, 0);
-#endif /* AFS_PTHREAD_ENV */
     for (i = 0; i < (h_HTSPERBLOCK); i++)
        Lock_Init(&block->entry[i].lock);
     for (i = 0; i < (h_HTSPERBLOCK - 1); i++)
@@ -282,7 +275,7 @@ hpr_Initialize(struct ubik_client **uclient)
     code = afsconf_GetCellInfo(tdir, cellstr, "afsprot", &info);
     if (code) {
        ViceLog(0, ("hpr_Initialize: Could not locate cell %s in %s/%s",
-                   cellstr, confDir->name, AFSDIR_CELLSERVDB_FILE));
+                   cellstr, tdir->name, AFSDIR_CELLSERVDB_FILE));
        afsconf_Close(tdir);
        return code;
     }
@@ -337,22 +330,34 @@ hpr_End(struct ubik_client *uclient)
     return code;
 }
 
+static_inline int
+getThreadClient(struct ubik_client **client)
+{
+    int code;
+
+    *client = pthread_getspecific(viced_uclient_key);
+    if (*client != NULL)
+       return 0;
+
+    code = hpr_Initialize(client);
+    if (code)
+       return code;
+
+    osi_Assert(pthread_setspecific(viced_uclient_key, *client) == 0);
+
+    return 0;
+}
+
 int
 hpr_GetHostCPS(afs_int32 host, prlist *CPS)
 {
-#ifdef AFS_PTHREAD_ENV
     afs_int32 code;
     afs_int32 over;
-    struct ubik_client *uclient =
-       (struct ubik_client *)pthread_getspecific(viced_uclient_key);
+    struct ubik_client *uclient;
 
-    if (!uclient) {
-        code = hpr_Initialize(&uclient);
-       if (!code)
-           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
-       else
-           return code;
-    }
+    code = getThreadClient(&uclient);
+    if (code)
+       return code;
 
     over = 0;
     code = ubik_PR_GetHostCPS(uclient, 0, host, CPS, &over);
@@ -366,76 +371,49 @@ hpr_GetHostCPS(afs_int32 host, prlist *CPS)
                 host);
     }
     return 0;
-#else
-    return pr_GetHostCPS(host, CPS);
-#endif
 }
 
 int
 hpr_NameToId(namelist *names, idlist *ids)
 {
-#ifdef AFS_PTHREAD_ENV
     afs_int32 code;
     afs_int32 i;
-    struct ubik_client *uclient =
-       (struct ubik_client *)pthread_getspecific(viced_uclient_key);
+    struct ubik_client *uclient;
 
-    if (!uclient) {
-        code = hpr_Initialize(&uclient);
-       if (!code)
-           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
-       else
-           return code;
-    }
+    code = getThreadClient(&uclient);
+    if (code)
+       return code;
 
     for (i = 0; i < names->namelist_len; i++)
         stolower(names->namelist_val[i]);
     code = ubik_PR_NameToID(uclient, 0, names, ids);
     return code;
-#else
-    return pr_NameToId(names, ids);
-#endif
 }
 
 int
 hpr_IdToName(idlist *ids, namelist *names)
 {
-#ifdef AFS_PTHREAD_ENV
     afs_int32 code;
-    struct ubik_client *uclient =
-       (struct ubik_client *)pthread_getspecific(viced_uclient_key);
+    struct ubik_client *uclient;
 
-    if (!uclient) {
-        code = hpr_Initialize(&uclient);
-       if (!code)
-           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
-       else
-           return code;
-    }
+    code = getThreadClient(&uclient);
+    if (code)
+       return code;
 
     code = ubik_PR_IDToName(uclient, 0, ids, names);
     return code;
-#else
-    return pr_IdToName(ids, names);
-#endif
 }
 
 int
 hpr_GetCPS(afs_int32 id, prlist *CPS)
 {
-#ifdef AFS_PTHREAD_ENV
     afs_int32 code;
     afs_int32 over;
-    struct ubik_client *uclient =
-       (struct ubik_client *)pthread_getspecific(viced_uclient_key);
+    struct ubik_client *uclient;
 
-    if (!uclient) {
-        code = hpr_Initialize(&uclient);
-       if (!code)
-           osi_Assert(pthread_setspecific(viced_uclient_key, (void *)uclient) == 0);
-       else
-           return code;
-    }
+    code = getThreadClient(&uclient);
+    if (code)
+       return code;
 
     over = 0;
     code = ubik_PR_GetCPS(uclient, 0, id, CPS, &over);
@@ -448,9 +426,6 @@ hpr_GetCPS(afs_int32 id, prlist *CPS)
                 id);
     }
     return 0;
-#else
-    return pr_GetCPS(id, CPS);
-#endif
 }
 
 static short consolePort = 0;
@@ -580,12 +555,7 @@ h_gethostcps_r(struct host *host, afs_int32 now)
     while (host->hostFlags & HCPS_INPROGRESS) {
        slept = 1;              /* I did sleep */
        host->hostFlags |= HCPS_WAITING;        /* I am sleeping now */
-#ifdef AFS_PTHREAD_ENV
        CV_WAIT(&host->cond, &host_glock_mutex);
-#else /* AFS_PTHREAD_ENV */
-       if ((code = LWP_WaitProcess(&(host->hostFlags))) != LWP_SUCCESS)
-           ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
-#endif /* AFS_PTHREAD_ENV */
     }
 
 
@@ -641,12 +611,7 @@ h_gethostcps_r(struct host *host, afs_int32 now)
     /* signal all who are waiting */
     if (host->hostFlags & HCPS_WAITING) {      /* somebody is waiting */
        host->hostFlags &= ~HCPS_WAITING;
-#ifdef AFS_PTHREAD_ENV
        CV_BROADCAST(&host->cond);
-#else /* AFS_PTHREAD_ENV */
-       if ((code = LWP_NoYieldSignal(&(host->hostFlags))) != LWP_SUCCESS)
-           ViceLog(0, ("LWP_NoYieldSignal returns %d\n", code));
-#endif /* AFS_PTHREAD_ENV */
     }
 }
 
@@ -684,6 +649,12 @@ h_Alloc_r(struct rx_connection *r_con)
     if (!host)
        return NULL;
 
+    h_Hold_r(host);
+    /* acquire the host lock withot dropping H_LOCK. we can do this here
+     * because we know we will not block; we just created this host and
+     * nobody else knows about it. */
+    ObtainWriteLock(&host->lock);
+
     host->host = rxr_HostOf(r_con);
     host->port = rxr_PortOf(r_con);
 
@@ -715,8 +686,6 @@ h_Alloc_r(struct rx_connection *r_con)
     h_gethostcps(host);                /* do this under host hold/lock */
 #endif
     host->FirstClient = NULL;
-    h_Hold_r(host);
-    h_Lock_r(host);
     h_InsertList_r(host);      /* update global host List */
     /*
      * Compare the new host's IP address (in host byte order) with ours
@@ -830,6 +799,11 @@ h_TossStuff_r(struct host *host)
 {
     struct client **cp, *client;
     int code;
+    int wasdeleted = 0;
+
+    if ((host->hostFlags & HOSTDELETED)) {
+       wasdeleted = 1;
+    }
 
     /* make sure host doesn't go away over h_NBLock_r */
     h_Hold_r(host);
@@ -842,9 +816,13 @@ h_TossStuff_r(struct host *host)
     /* if somebody still has this host locked */
     if (code != 0) {
        char hoststr[16];
-       ViceLog(0,
-               ("Warning:  h_TossStuff_r failed; Host %" AFS_PTR_FMT " (%s:%d) was locked.\n",
-                host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
+       if (wasdeleted) {
+           /* someone locked the host while HOSTDELETED was set; that is bad */
+           ViceLog(0, ("Warning:  h_TossStuff_r failed; Host %" AFS_PTR_FMT
+                       " (%s:%d flags 0x%x) was locked.\n",
+                       host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
+                       (unsigned)host->hostFlags));
+       }
        return;
     } else {
        h_Unlock_r(host);
@@ -855,9 +833,13 @@ h_TossStuff_r(struct host *host)
      * reacquire H_LOCK */
     if (host->refCount > 0) {
        char hoststr[16];
-       ViceLog(0,
-               ("Warning:  h_TossStuff_r failed; Host %" AFS_PTR_FMT " (%s:%d) was held.\n",
-                host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
+       if (wasdeleted) {
+           /* someone grabbed a ref while HOSTDELETED was set; that is bad */
+           ViceLog(0, ("Warning:  h_TossStuff_r failed; Host %" AFS_PTR_FMT
+                       " (%s:%d flags 0x%x) was held.\n",
+                       host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
+                       (unsigned)host->hostFlags));
+       }
        return;
     }
 
@@ -970,7 +952,7 @@ h_Enumerate(int (*proc) (struct host*, void *), void *param)
        H_UNLOCK;
        return;
     }
-    list = (struct host **)malloc(hostCount * sizeof(struct host *));
+    list = malloc(hostCount * sizeof(struct host *));
     if (!list) {
        ViceLogThenPanic(0, ("Failed malloc in h_Enumerate (list)\n"));
     }
@@ -1015,7 +997,7 @@ h_Enumerate(int (*proc) (struct host*, void *), void *param)
        }
        H_UNLOCK;
     }
-    free((void *)list);
+    free(list);
 }      /* h_Enumerate */
 
 
@@ -1146,7 +1128,7 @@ h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host)
     }
 
     /* insert into beginning of list for this bucket */
-    chain = (struct h_UuidHashChain *)malloc(sizeof(struct h_UuidHashChain));
+    chain = malloc(sizeof(struct h_UuidHashChain));
     if (!chain) {
        ViceLogThenPanic(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n"));
     }
@@ -1327,7 +1309,7 @@ createHostAddrHashChain_r(int index, afs_uint32 addr, afs_uint16 port, struct ho
     char hoststr[16];
 
     /* insert into beginning of list for this bucket */
-    chain = (struct h_AddrHashChain *)malloc(sizeof(struct h_AddrHashChain));
+    chain = malloc(sizeof(struct h_AddrHashChain));
     if (!chain) {
        ViceLogThenPanic(0, ("Failed malloc in h_AddHostToAddrHashTable_r\n"));
     }
@@ -1546,8 +1528,8 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
                  ntohs(host->port), afs_inet_ntoa_r(addr, hoststr2),
                  ntohs(port)));
 
-    interface = (struct Interface *)
-       malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * number));
+    interface = malloc(sizeof(struct Interface)
+                      + (sizeof(struct AddrPort) * number));
     if (!interface) {
        ViceLogThenPanic(0, ("Failed malloc in addInterfaceAddr_r\n"));
     }
@@ -1740,7 +1722,7 @@ h_GetHost_r(struct rx_connection *tcon)
        H_LOCK;
        if ((code == RXGEN_OPCODE) ||
            ((code == 0) && (afs_uuid_equal(&interf.uuid, &nulluuid)))) {
-           identP = (struct Identity *)malloc(sizeof(struct Identity));
+           identP = malloc(sizeof(struct Identity));
            if (!identP) {
                ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
            }
@@ -1781,7 +1763,7 @@ h_GetHost_r(struct rx_connection *tcon)
            }
        } else if (code == 0) {
            interfValid = 1;
-           identP = (struct Identity *)malloc(sizeof(struct Identity));
+           identP = malloc(sizeof(struct Identity));
            if (!identP) {
                ViceLogThenPanic(0, ("Failed malloc in h_GetHost_r\n"));
            }
@@ -1967,8 +1949,7 @@ h_GetHost_r(struct rx_connection *tcon)
            if ((code == RXGEN_OPCODE) ||
                ((code == 0) && (afs_uuid_equal(&interf.uuid, &nulluuid)))) {
                if (!identP)
-                   identP =
-                       (struct Identity *)malloc(sizeof(struct Identity));
+                   identP = malloc(sizeof(struct Identity));
                else
                    pident = 1;
 
@@ -1985,8 +1966,7 @@ h_GetHost_r(struct rx_connection *tcon)
                code = 0;
            } else if (code == 0) {
                if (!identP)
-                   identP =
-                       (struct Identity *)malloc(sizeof(struct Identity));
+                   identP = malloc(sizeof(struct Identity));
                else
                    pident = 1;
 
@@ -2027,6 +2007,17 @@ h_GetHost_r(struct rx_connection *tcon)
                if (oldHost) {
                    int probefail = 0;
 
+                   /* This is a new address for an existing host. Update
+                    * the list of interfaces for the existing host and
+                    * delete the host structure we just allocated. */
+
+                   /* mark the duplicate host as deleted before we do
+                    * anything. The probing code below may try to change
+                    * "oldHost" to the same IP address as "host" currently
+                    * has, and we do not want a pseudo-"collision" to be
+                    * noticed. */
+                   host->hostFlags |= HOSTDELETED;
+
                    oldHost->hostFlags |= HWHO_INPROGRESS;
 
                     if (oldHost->interface) {
@@ -2053,20 +2044,22 @@ h_GetHost_r(struct rx_connection *tcon)
                                         oldHost,
                                          afs_inet_ntoa_r(oldHost->host, hoststr),
                                         ntohs(oldHost->port),code2));
-                           MultiProbeAlternateAddress_r(oldHost);
-                            probefail = 1;
+
+                           if (MultiProbeAlternateAddress_r(oldHost)) {
+                               /* If MultiProbeAlternateAddress_r succeeded,
+                                * it updated oldHost->host and oldHost->port
+                                * to an address that responded successfully to
+                                * a ProbeUuid, so it is as if the ProbeUuid
+                                * call above returned success. So, only set
+                                * 'probefail' if MultiProbeAlternateAddress_r
+                                * fails. */
+                               probefail = 1;
+                           }
                         }
                     } else {
                         probefail = 1;
                     }
 
-                   /* This is a new address for an existing host. Update
-                    * the list of interfaces for the existing host and
-                    * delete the host structure we just allocated. */
-
-                    /* prevent warnings while manipulating interface lists */
-                   host->hostFlags |= HOSTDELETED;
-
                    if (oldHost->host != haddr || oldHost->port != hport) {
                        struct rx_connection *rxconn;
 
@@ -2110,7 +2103,6 @@ h_GetHost_r(struct rx_connection *tcon)
                                }
                            }
                        }
-                       h_AddHostToAddrHashTable_r(haddr, hport, oldHost);
                        oldHost->host = haddr;
                        oldHost->port = hport;
                        rxconn = oldHost->callback_rxcon;
@@ -2185,8 +2177,6 @@ h_GetHost_r(struct rx_connection *tcon)
 
 
 static char localcellname[PR_MAXNAMELEN + 1];
-char local_realms[AFS_NUM_LREALMS][AFS_REALM_SZ];
-int  num_lrealms = -1;
 
 /* not reentrant */
 void
@@ -2194,76 +2184,23 @@ h_InitHostPackage(void)
 {
     memset(&nulluuid, 0, sizeof(afsUUID));
     afsconf_GetLocalCell(confDir, localcellname, PR_MAXNAMELEN);
-    if (num_lrealms == -1) {
-       int i;
-       for (i=0; i<AFS_NUM_LREALMS; i++) {
-           if (afs_krb_get_lrealm(local_realms[i], i) != 0 /*KSUCCESS*/)
-               break;
-       }
-
-       if (i == 0) {
-           ViceLog(0,
-                   ("afs_krb_get_lrealm failed, using %s.\n",
-                    localcellname));
-           strncpy(local_realms[0], localcellname, AFS_REALM_SZ);
-           num_lrealms = i =1;
-       } else {
-           num_lrealms = i;
-       }
-
-       /* initialize the rest of the local realms to nullstring for debugging */
-       for (; i<AFS_NUM_LREALMS; i++)
-           local_realms[i][0] = '\0';
-    }
     rxcon_ident_key = rx_KeyCreate((rx_destructor_t) free);
     rxcon_client_key = rx_KeyCreate((rx_destructor_t) 0);
     MUTEX_INIT(&host_glock_mutex, "host glock", MUTEX_DEFAULT, 0);
 }
 
 static int
-MapName_r(char *aname, char *acell, afs_int32 * aval)
+MapName_r(char *uname, afs_int32 * aval)
 {
     namelist lnames;
     idlist lids;
     afs_int32 code;
-    afs_int32 anamelen, cnamelen;
-    int foreign = 0;
-    char *tname;
-
-    anamelen = strlen(aname);
-    if (anamelen >= PR_MAXNAMELEN)
-       return -1;              /* bad name -- caller interprets this as anonymous, but retries later */
 
     lnames.namelist_len = 1;
-    lnames.namelist_val = (prname *) aname;    /* don't malloc in the common case */
+    lnames.namelist_val = (prname *) uname;
     lids.idlist_len = 0;
     lids.idlist_val = NULL;
 
-    cnamelen = strlen(acell);
-    if (cnamelen) {
-       if (afs_is_foreign_ticket_name(aname, NULL, acell, localcellname)) {
-           ViceLog(2,
-                   ("MapName: cell is foreign.  cell=%s, localcell=%s, localrealms={%s,%s,%s,%s}\n",
-                   acell, localcellname, local_realms[0],local_realms[1],local_realms[2],local_realms[3]));
-           if ((anamelen + cnamelen + 1) >= PR_MAXNAMELEN) {
-               ViceLog(2,
-                       ("MapName: Name too long, using AnonymousID for %s@%s\n",
-                        aname, acell));
-               *aval = AnonymousID;
-               return 0;
-           }
-           foreign = 1;        /* attempt cross-cell authentication */
-           tname = (char *)malloc(PR_MAXNAMELEN);
-           if (!tname) {
-               ViceLogThenPanic(0, ("Failed malloc in MapName_r\n"));
-           }
-           strcpy(tname, aname);
-           tname[anamelen] = '@';
-           strcpy(tname + anamelen + 1, acell);
-           lnames.namelist_val = (prname *) tname;
-       }
-    }
-
     H_UNLOCK;
     code = hpr_NameToId(&lnames, &lids);
     H_LOCK;
@@ -2283,10 +2220,6 @@ MapName_r(char *aname, char *acell, afs_int32 * aval)
            code = -1;
        }
     }
-
-    if (foreign) {
-       free(lnames.namelist_val);      /* We allocated this above, so we must free it now. */
-    }
     return code;
 }
 
@@ -2325,6 +2258,102 @@ h_ID2Client(afs_int32 vid)
     return NULL;
 }
 
+static int
+format_vname(char *vname, int usize, const char *tname, const char *tinst,
+            const char *tcell, afs_int32 islocal)
+{
+    int len;
+
+    len = strlcpy(vname, tname, usize);
+    if (len >= usize)
+       return -1;
+    if (tinst[0]) {
+       len = strlcat(vname, ".", usize);
+       if (len >= usize)
+           return -1;
+       len = strlcat(vname, tinst, usize);
+       if (len >= usize)
+           return -1;
+    }
+    if (tcell[0] && !islocal) {
+       len = strlcat(vname, "@", usize);
+       if (len >= usize)
+           return -1;
+       len = strlcat(vname, tcell, usize);
+       if (len >= usize)
+           return -1;
+    }
+    return 0;
+}
+
+static int
+getPeerDetails(struct rx_connection *conn,
+              afs_int32 *viceid, afs_int32 *expTime, int authClass)
+{
+    int code;
+#if (64-MAXKTCNAMELEN)
+    ticket name length != 64
+#endif
+    char tname[64];
+    char tinst[64];
+    char tcell[MAXKTCREALMLEN];
+    char uname[PR_MAXNAMELEN];
+
+    *viceid = AnonymousID;
+    *expTime = 0x7fffffff;
+
+    ViceLog(5,
+           ("FindClient: authenticating connection: authClass=%d\n",
+            authClass));
+    if (authClass == 1) {
+       /* A bcrypt tickets, no longer supported */
+       ViceLog(1, ("FindClient: bcrypt ticket, using AnonymousID\n"));
+       return 0;
+    }
+
+    if (authClass == 2) {
+       /* an rxkad ticket */
+       afs_int32 kvno;
+       afs_int32 islocal;
+
+       /* kerberos ticket */
+       code = rxkad_GetServerInfo(conn, /*level */ 0, (afs_uint32 *)expTime,
+                                  tname, tinst, tcell, &kvno);
+       if (code) {
+           ViceLog(1, ("Failed to get rxkad ticket info\n"));
+           return 0;
+       }
+
+       ViceLog(5,
+               ("FindClient: rxkad conn: name=%s,inst=%s,cell=%s,exp=%d,kvno=%d\n",
+                tname, tinst, tcell, *expTime, kvno));
+       code = afsconf_IsLocalRealmMatch(confDir, &islocal, tname, tinst, tcell);
+
+       if (code) {
+           ViceLog(0, ("FindClient: local realm check failed; code=%d", code));
+           return 0;
+       }
+
+       code = format_vname(uname, sizeof(uname), tname, tinst, tcell, islocal);
+       if (code) {
+           ViceLog(0, ("FindClient: uname truncated."));
+           return 0;
+       }
+
+       /* translate the name to a vice id */
+       code = MapName_r(uname, viceid);
+       if (code) {
+           ViceLog(1, ("failed to map name=%s -> code=%d\n", uname,
+                       code));
+           return code; /* Actually flag this is a failure */
+       }
+
+       return 0;
+    }
+
+    return 0;
+}
+
 /*
  * Called by the server main loop.  Returns a h_Held client, which must be
  * released later the main loop.  Allocates a client if the matching one
@@ -2345,13 +2374,7 @@ h_FindClient_r(struct rx_connection *tcon)
     afs_int32 expTime;
     afs_int32 code;
     int authClass;
-#if (64-MAXKTCNAMELEN)
-    ticket name length != 64
-#endif
-    char tname[64];
-    char tinst[64];
-    char uname[PR_MAXNAMELEN];
-    char tcell[MAXKTCREALMLEN];
+
     int fail = 0;
     int created = 0;
 
@@ -2379,53 +2402,11 @@ h_FindClient_r(struct rx_connection *tcon)
        client = NULL;
     }
 
-    authClass = rx_SecurityClassOf((struct rx_connection *)tcon);
-    ViceLog(5,
-           ("FindClient: authenticating connection: authClass=%d\n",
-            authClass));
-    if (authClass == 1) {
-       /* A bcrypt tickets, no longer supported */
-       ViceLog(1, ("FindClient: bcrypt ticket, using AnonymousID\n"));
-       viceid = AnonymousID;
-       expTime = 0x7fffffff;
-    } else if (authClass == 2) {
-       afs_int32 kvno;
+    authClass = rx_SecurityClassOf(tcon);
 
-       /* kerberos ticket */
-       code = rxkad_GetServerInfo(tcon, /*level */ 0, (afs_uint32 *)&expTime,
-                                  tname, tinst, tcell, &kvno);
-       if (code) {
-           ViceLog(1, ("Failed to get rxkad ticket info\n"));
-           viceid = AnonymousID;
-           expTime = 0x7fffffff;
-       } else {
-           int ilen = strlen(tinst);
-           ViceLog(5,
-                   ("FindClient: rxkad conn: name=%s,inst=%s,cell=%s,exp=%d,kvno=%d\n",
-                    tname, tinst, tcell, expTime, kvno));
-           strncpy(uname, tname, sizeof(uname));
-           if (ilen) {
-               if (strlen(uname) + 1 + ilen >= sizeof(uname))
-                   goto bad_name;
-               strcat(uname, ".");
-               strcat(uname, tinst);
-           }
-           /* translate the name to a vice id */
-           code = MapName_r(uname, tcell, &viceid);
-           if (code) {
-             bad_name:
-               ViceLog(1,
-                       ("failed to map name=%s, cell=%s -> code=%d\n", uname,
-                        tcell, code));
-               fail = 1;
-               viceid = AnonymousID;
-               expTime = 0x7fffffff;
-           }
-       }
-    } else {
-       viceid = AnonymousID;   /* unknown security class */
-       expTime = 0x7fffffff;
-    }
+    code = getPeerDetails(tcon, &viceid, &expTime, authClass);
+    if (code)
+       fail = 1;
 
     if (!client) { /* loop */
        host = h_GetHost_r(tcon);       /* Returns with incremented refCount  */
@@ -2705,7 +2686,7 @@ h_UserName(struct client *client)
     idlist lids;
 
     lids.idlist_len = 1;
-    lids.idlist_val = (afs_int32 *) malloc(1 * sizeof(afs_int32));
+    lids.idlist_val = malloc(1 * sizeof(afs_int32));
     if (!lids.idlist_val) {
        ViceLogThenPanic(0, ("Failed malloc in h_UserName\n"));
     }
@@ -3287,7 +3268,7 @@ h_stateSaveHost(struct host * host, void* rock)
     if (host->interface) {
        if_len = sizeof(struct Interface) +
            ((host->interface->numberOfInterfaces-1) * sizeof(struct AddrPort));
-       ifp = (struct Interface *) malloc(if_len);
+       ifp = malloc(if_len);
        osi_Assert(ifp != NULL);
        memcpy(ifp, host->interface, if_len);
        hdr.interfaces = host->interface->numberOfInterfaces;
@@ -3298,7 +3279,7 @@ h_stateSaveHost(struct host * host, void* rock)
     if (host->hcps.prlist_val) {
        hdr.hcps = host->hcps.prlist_len;
        hcps_len = hdr.hcps * sizeof(afs_int32);
-       hcps = (afs_int32 *) malloc(hcps_len);
+       hcps = malloc(hcps_len);
        osi_Assert(hcps != NULL);
        memcpy(hcps, host->hcps.prlist_val, hcps_len);
        iov[iovcnt].iov_base = (char *) hcps;
@@ -3370,7 +3351,7 @@ h_stateRestoreHost(struct fs_dump_state * state)
     if (hdr.interfaces) {
        ifp_len = sizeof(struct Interface) +
            ((hdr.interfaces-1) * sizeof(struct AddrPort));
-       ifp = (struct Interface *) malloc(ifp_len);
+       ifp = malloc(ifp_len);
        osi_Assert(ifp != NULL);
        iov[iovcnt].iov_base = (char *) ifp;
        iov[iovcnt].iov_len = ifp_len;
@@ -3378,7 +3359,7 @@ h_stateRestoreHost(struct fs_dump_state * state)
     }
     if (hdr.hcps) {
        hcps_len = hdr.hcps * sizeof(afs_int32);
-       hcps = (afs_int32 *) malloc(hcps_len);
+       hcps = malloc(hcps_len);
        osi_Assert(hcps != NULL);
        iov[iovcnt].iov_base = (char *) hcps;
        iov[iovcnt].iov_len = hcps_len;
@@ -3399,7 +3380,7 @@ h_stateRestoreHost(struct fs_dump_state * state)
 
     if (!hdr.hcps && hdsk.hcps_valid) {
        /* valid, zero-length host cps ; does this ever happen? */
-       hcps = (afs_int32 *) malloc(sizeof(afs_int32));
+       hcps = malloc(sizeof(afs_int32));
        osi_Assert(hcps != NULL);
     }
 
@@ -4064,7 +4045,7 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
 
     /*
      * Convert IP addresses to network byte order, and remove
-     * duplicate IP addresses from the interface list, and
+     * duplicate and loopback IP addresses from the interface list, and
      * determine whether or not the incoming addr/port is
      * listed.  Note that if the address matches it is not
      * truly a match because the port number for the entries
@@ -4072,6 +4053,9 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
      * for this connection might not be 7001.
      */
     for (i = 0, count = 0, found = 0; i < number; i++) {
+       if (rx_IsLoopbackAddr(interf->addr_in[i])) {
+           continue;
+       }
        interf->addr_in[i] = htonl(interf->addr_in[i]);
        for (j = 0; j < count; j++) {
            if (interf->addr_in[j] == interf->addr_in[i])
@@ -4090,16 +4074,15 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
      * Allocate and initialize an interface structure for this host.
      */
     if (found) {
-       interface = (struct Interface *)
-           malloc(sizeof(struct Interface) +
-                  (sizeof(struct AddrPort) * (count - 1)));
+       interface = malloc(sizeof(struct Interface) +
+                          (sizeof(struct AddrPort) * (count - 1)));
        if (!interface) {
            ViceLogThenPanic(0, ("Failed malloc in initInterfaceAddr_r 1\n"));
        }
        interface->numberOfInterfaces = count;
     } else {
-       interface = (struct Interface *)
-           malloc(sizeof(struct Interface) + (sizeof(struct AddrPort) * count));
+       interface = malloc(sizeof(struct Interface) +
+                          (sizeof(struct AddrPort) * count));
        if (!interface) {
            ViceLogThenPanic(0, ("Failed malloc in initInterfaceAddr_r 2\n"));
        }