Add interface to select client security objects
[openafs.git] / src / viced / host.c
index 9bd3b6e..89efeb7 100644 (file)
@@ -266,9 +266,8 @@ hpr_Initialize(struct ubik_client **uclient)
 {
     afs_int32 code;
     struct rx_connection *serverconns[MAXSERVERS];
-    struct rx_securityClass *sc[3];
+    struct rx_securityClass *sc;
     struct afsconf_dir *tdir;
-    struct ktc_token ttoken;
     afs_int32 scIndex;
     struct afsconf_cell info;
     afs_int32 i;
@@ -289,7 +288,8 @@ 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, AFSDIR_CELLSERVDB_FILE));
+       ViceLog(0, ("hpr_Initialize: Could not locate cell %s in %s/%s",
+                   cellstr, confDir->name, AFSDIR_CELLSERVDB_FILE));
        afsconf_Close(tdir);
        return code;
     }
@@ -301,55 +301,29 @@ hpr_Initialize(struct ubik_client **uclient)
         return code;
     }
     
-    scIndex = 2;
-    sc[0] = 0;
-    sc[1] = 0;
-    sc[2] = 0;
     /* Most callers use secLevel==1, however, the fileserver uses secLevel==2
      * to force use of the KeyFile.  secLevel == 0 implies -noauth was
      * specified. */
     if ((afsconf_GetLatestKey(tdir, 0, 0) == 0)) {
-        code = afsconf_ClientAuthSecure(tdir, &sc[2], &scIndex);
+        code = afsconf_ClientAuthSecure(tdir, &sc, &scIndex);
         if (code)
            ViceLog(0, ("hpr_Initialize: clientauthsecure returns %d %s (so trying noauth)", code, afs_error_message(code)));
         if (code)
             scIndex = 0;        /* use noauth */
-        if (scIndex != 2)
-            /* if there was a problem, an unauthenticated conn is returned */
-            sc[scIndex] = sc[2];
     } else {
-        struct ktc_principal sname;
-        strcpy(sname.cell, info.name);
-        sname.instance[0] = 0;
-        strcpy(sname.name, "afs");
-        code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL);
-        if (code)
-            scIndex = 0;
-        else {
-            if (ttoken.kvno >= 0 && ttoken.kvno <= 256)
-                /* this is a kerberos ticket, set scIndex accordingly */
-                scIndex = 2;
-            else {
-                ViceLog(0, ("hpr_Initialize: funny kvno (%d) in ticket, proceeding", ttoken.kvno));
-                scIndex = 2;
-            }
-            sc[2] =
-                rxkad_NewClientSecurityObject(rxkad_clear, &ttoken.sessionKey,
-                                              ttoken.kvno, ttoken.ticketLen,
-                                              ttoken.ticket);
-        }
+       afsconf_ClientAuthToken(&info, 0, &sc, &scIndex, NULL);
     }
-    if ((scIndex == 0) && (sc[0] == 0))
-        sc[0] = rxnull_NewClientSecurityObject();
-    if ((scIndex == 0))
+    if ((scIndex == 0) && (sc == NULL))
+        sc = rxnull_NewClientSecurityObject();
+    if (scIndex == 0)
        ViceLog(0, ("hpr_Initialize: Could not get afs tokens, running unauthenticated. [%d]", code));
     
     memset(serverconns, 0, sizeof(serverconns));        /* terminate list!!! */
     for (i = 0; i < info.numServers; i++) {
         serverconns[i] =
             rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
-                             info.hostAddr[i].sin_port, PRSRV, sc[scIndex],
-                             scIndex);
+                             info.hostAddr[i].sin_port, PRSRV,
+                            sc, scIndex);
     }
 
     code = ubik_ClientInit(serverconns, uclient);
@@ -357,7 +331,7 @@ hpr_Initialize(struct ubik_client **uclient)
        ViceLog(0, ("hpr_Initialize: ubik client init failed. [%d]", code));
     }
     afsconf_Close(tdir);
-    code = rxs_Release(sc[scIndex]);
+    code = rxs_Release(sc);
     return code;
 }
 
@@ -659,12 +633,12 @@ h_gethostcps_r(register struct host *host, register afs_int32 now)
             */
            host->hcpsfailed = 1;
            ViceLog(0,
-                   ("Warning:  GetHostCPS failed (%d) for %x (%s:%d); will retry\n",
+                   ("Warning:  GetHostCPS failed (%d) for %p (%s:%d); will retry\n",
                     code, host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
        } else {
            host->hcpsfailed = 0;
            ViceLog(1,
-                   ("gethost:  GetHostCPS failed (%d) for %x (%s:%d); ignored\n",
+                   ("gethost:  GetHostCPS failed (%d) for %p (%s:%d); ignored\n",
                     code, host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
        }
        if (host->hcps.prlist_val)
@@ -892,7 +866,8 @@ h_TossStuff_r(register struct host *host)
            if (code < 0) {
                char hoststr[16];
                ViceLog(0,
-                       ("Warning: h_TossStuff_r failed: Host %" AFS_PTR_FMT " (%s:%d) client %x was locked.\n",
+                       ("Warning: h_TossStuff_r failed: Host %p (%s:%d) "
+                        "client %p was locked.\n",
                         host, afs_inet_ntoa_r(host->host, hoststr),
                         ntohs(host->port), client));
                return;
@@ -901,7 +876,8 @@ h_TossStuff_r(register struct host *host)
            if (client->refCount) {
                char hoststr[16];
                ViceLog(0,
-                       ("Warning: h_TossStuff_r failed: Host %" AFS_PTR_FMT " (%s:%d) client %x refcount %d.\n",
+                       ("Warning: h_TossStuff_r failed: Host %p (%s:%d) "
+                        "client %p refcount %d.\n",
                         host, afs_inet_ntoa_r(host->host, hoststr),
                         ntohs(host->port), client, client->refCount));
                /* This is the same thing we do if the host is locked */
@@ -1005,14 +981,16 @@ h_Enumerate(int (*proc) (struct host*, int, void *), void *param)
        ViceLog(0, ("Failed malloc in h_Enumerate (flags)\n"));
        assert(0);
     }
-    for (count = 0, host = hostList; host; host = host->next, count++) {
+    for (count = 0, host = hostList; host && count < hostCount; host = host->next, count++) {
        list[count] = host;
        h_Hold_r(host);
     }
     if (count != hostCount) {
        ViceLog(0, ("h_Enumerate found %d of %d hosts\n", count, hostCount));
+    } else if (host != NULL) {
+       ViceLog(0, ("h_Enumerate found more than %d hosts\n", hostCount));
+       ShutDownAndCore(PANIC);
     }
-    assert(count <= hostCount);
     H_UNLOCK;
     for (i = 0; i < count; i++) {
        flags[i] = (*proc) (list[i], flags[i], param);
@@ -1046,12 +1024,13 @@ h_Enumerate_r(int (*proc) (struct host *, int, void *),
     register struct host *host, *next;
     int flags = 0;
     int nflags = 0;
+    int count;
 
     if (hostCount == 0) {
        return;
     }
     h_Hold_r(enumstart);
-    for (host = enumstart; host; host = next, flags = nflags) {
+    for (count = 0, host = enumstart; host && count < hostCount; host = next, flags = nflags, count++) {
        next = host->next;
        if (next && !H_ENUMERATE_ISSET_BAIL(flags))
            h_Hold_r(next);
@@ -1062,6 +1041,10 @@ h_Enumerate_r(int (*proc) (struct host *, int, void *),
        }
        h_Release_r(host); /* this might free up the host */
     }
+    if (host != NULL) {
+       ViceLog(0, ("h_Enumerate_r found more than %d hosts\n", hostCount));
+       ShutDownAndCore(PANIC);
+    }
 }      /*h_Enumerate_r */
 
 
@@ -1110,9 +1093,9 @@ h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host)
               return;
      afsUUID_to_string(uuid, uuid2, 127);
      ViceLog(125, 
-            ("h_AddHostToUuidHashTable_r: host %" AFS_PTR_FMT " (%s:%d) added as uuid %s\n",
+            ("h_AddHostToUuidHashTable_r: host %p (%s:%d) added as uuid %s\n",
              host, afs_inet_ntoa_r(chain->hostPtr->host, hoststr), 
-             ntohs(chain->hostPtr->port), uuid));
+             ntohs(chain->hostPtr->port), uuid2));
 }
 
 /* deletes a HashChain structure corresponding to this host */
@@ -1157,27 +1140,29 @@ h_AddHostToAddrHashTable_r(afs_uint32 addr, afs_uint16 port, struct host *host)
 {
     int index;
     struct h_AddrHashChain *chain;
-    char hoststr[16], hoststr2[16];
+    char hoststr[16];
 
     /* hash into proper bucket */
     index = h_HashIndex(addr);
 
-    /* don't add the same entry multiple times */
+    /* don't add the same address:port pair entry multiple times */
     for (chain = hostAddrHashTable[index]; chain; chain = chain->next) {
-       if (chain->hostPtr == host) {
-           if (chain->addr != addr || chain->port != port) {
-               ViceLog(0, 
-                       ("h_AddHostToAddrHashTable_r: host %" AFS_PTR_FMT " exists as %s:%d when adding %s:%d\n",
-                        host, afs_inet_ntoa_r(chain->addr, hoststr), 
-                        ntohs(chain->port), afs_inet_ntoa_r(addr, hoststr2), 
-                        ntohs(port)));
-           } else
-               ViceLog(125, 
-                       ("h_AddHostToAddrHashTable_r: host %" AFS_PTR_FMT " (%s:%d) already hashed\n",
-                        host, afs_inet_ntoa_r(chain->addr, hoststr), 
-                        ntohs(chain->port)));
-           
-           return;
+       if (chain->addr == addr && chain->port == port) {
+           if (chain->hostPtr == host) {
+               ViceLog(125,
+                       ("h_AddHostToAddrHashTable_r: host %" AFS_PTR_FMT " (%s:%d) already hashed\n",
+                         host, afs_inet_ntoa_r(chain->addr, hoststr),
+                         ntohs(chain->port)));
+               return;
+           }
+           if (!(chain->hostPtr->hostFlags & HOSTDELETED)) {
+               ViceLog(0,
+                       ("h_AddHostToAddrHashTable_r: refusing to hash host %" AFS_PTR_FMT ", %"
+                        AFS_PTR_FMT " (%s:%d) already hashed\n",
+                        host, chain->hostPtr, afs_inet_ntoa_r(chain->addr, hoststr),
+                         ntohs(chain->port)));
+               return;
+           }
        }
     }
 
@@ -1501,8 +1486,11 @@ h_GetHost_r(struct rx_connection *tcon)
            goto gethost_out;
        }
        h_Lock_r(host);
-       if (!(host->hostFlags & ALTADDR)) {
-           /* Another thread is doing initialization */
+       if (!(host->hostFlags & ALTADDR) ||
+            (host->hostFlags & HOSTDELETED)) {
+           /* Another thread is doing initialization
+             * or this host was deleted while we
+             * waited for the lock. */
            h_Unlock_r(host);
            ViceLog(125,
                    ("Host %" AFS_PTR_FMT " (%s:%d) starting h_Lookup again\n",
@@ -1751,7 +1739,8 @@ h_GetHost_r(struct rx_connection *tcon)
            if (host->interface)
                afsUUID_to_string(&host->interface->uuid, uuid2, 127);
            ViceLog(0,
-                   ("CB: new identity for host %" AFS_PTR_FMT " (%s:%d), deleting(%x %x %s %s)\n",
+                   ("CB: new identity for host %p (%s:%d), "
+                    "deleting(%x %p %s %s)\n",
                     host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
                     identP->valid, host->interface,
                     identP->valid ? uuid1 : "no_uuid",
@@ -1832,10 +1821,19 @@ h_GetHost_r(struct rx_connection *tcon)
            } else if (code == 0) {
                oldHost = h_LookupUuid_r(&identP->uuid);
                 if (oldHost) {
-                    int probefail = 0;
-
                    h_Hold_r(oldHost);
                    h_Lock_r(oldHost);
+
+                   if (oldHost->hostFlags & HOSTDELETED) {
+                       h_Unlock_r(oldHost);
+                       h_Release_r(oldHost);
+                       oldHost = NULL;
+                   }
+               }
+
+               if (oldHost) {
+                   int probefail = 0;
+
                    oldHost->hostFlags |= HWHO_INPROGRESS;
 
                     if (oldHost->interface) {
@@ -2085,13 +2083,13 @@ MapName_r(char *aname, char *acell, afs_int32 * aval)
            if (*aval == AnonymousID) {
                ViceLog(2,
                        ("MapName: NameToId on %s returns anonymousID\n",
-                        lnames.namelist_val));
+                        lnames.namelist_val[0]));
            }
            free(lids.idlist_val);      /* return parms are not malloced in stub if server proc aborts */
        } else {
            ViceLog(0,
                    ("MapName: NameToId on '%s' is unknown\n",
-                    lnames.namelist_val));
+                    lnames.namelist_val[0]));
            code = -1;
        }
     }
@@ -2111,9 +2109,10 @@ h_ID2Client(afs_int32 vid)
 {
     register struct client *client;
     register struct host *host;
+    int count;
 
     H_LOCK;
-    for (host = hostList; host; host = host->next) {
+    for (count = 0, host = hostList; host && count < hostCount; host = host->next, count++) {
        if (host->hostFlags & HOSTDELETED)
            continue;
        for (client = host->FirstClient; client; client = client->next) {
@@ -2125,6 +2124,12 @@ h_ID2Client(afs_int32 vid)
            }
        }
     }
+    if (count != hostCount) {
+       ViceLog(0, ("h_ID2Client found %d of %d hosts\n", count, hostCount));
+    } else if (host != NULL) {
+       ViceLog(0, ("h_ID2Client found more than %d hosts\n", hostCount));
+       ShutDownAndCore(PANIC);
+    }
 
     H_UNLOCK;
     return NULL;
@@ -2233,7 +2238,7 @@ h_FindClient_r(struct rx_connection *tcon)
        host = h_GetHost_r(tcon);       /* Returns with incremented refCount  */
 
        if (!host) 
-           return 0;
+           return NULL;
 
     retryfirstclient:
        /* First try to find the client structure */
@@ -2251,6 +2256,11 @@ h_FindClient_r(struct rx_connection *tcon)
        /* Still no client structure - get one */
        if (!client) {
            h_Lock_r(host);
+            if (host->hostFlags & HOSTDELETED) {
+                h_Unlock_r(host);
+                h_Release_r(host);
+                return NULL;
+            }
            /* Retry to find the client structure */
            for (client = host->FirstClient; client; client = client->next) {
                if (!client->deleted && (client->sid == rxr_CidOf(tcon))
@@ -2338,7 +2348,8 @@ h_FindClient_r(struct rx_connection *tcon)
        if (!oldClient->deleted) {
            /* if we didn't create it, it's not ours to put back */
            if (created) {
-               ViceLog(0, ("FindClient: stillborn client %x(%x); conn %x (host %s:%d) had client %x(%x)\n", 
+               ViceLog(0, ("FindClient: stillborn client %p(%x); "
+                           "conn %p (host %s:%d) had client %p(%x)\n",
                            client, client->sid, tcon, 
                            afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
                            ntohs(rxr_PortOf(tcon)),
@@ -2361,7 +2372,8 @@ h_FindClient_r(struct rx_connection *tcon)
            H_LOCK;
            client = oldClient;
        } else {
-           ViceLog(0, ("FindClient: deleted client %x(%x) already had conn %x (host %s:%d), stolen by client %x(%x)\n", 
+           ViceLog(0, ("FindClient: deleted client %p(%x) already had "
+                       "conn %p (host %s:%d), stolen by client %p(%x)\n",
                        oldClient, oldClient->sid, tcon, 
                        afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
                        ntohs(rxr_PortOf(tcon)),
@@ -2372,6 +2384,25 @@ h_FindClient_r(struct rx_connection *tcon)
     /* Avoid chaining in more than once. */
     if (created) {
        h_Lock_r(host);
+
+        if (host->hostFlags & HOSTDELETED) {
+            h_Unlock_r(host);
+            h_Release_r(host);
+
+            host = NULL;
+            client->host = NULL;
+
+            if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val)
+                free(client->CPS.prlist_val);
+            client->CPS.prlist_val = NULL;
+            client->CPS.prlist_len = 0;
+
+            client->refCount--;
+            ReleaseWriteLock(&client->lock);
+            FreeCE(client);
+            return NULL;
+        }
+
        client->next = host->FirstClient;
        host->FirstClient = client;
        h_Unlock_r(host);
@@ -2411,7 +2442,7 @@ GetClient(struct rx_connection *tcon, struct client **cp)
     client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
     if (client == NULL) {
        ViceLog(0,
-               ("GetClient: no client in conn %x (host %s:%d), VBUSYING\n",
+               ("GetClient: no client in conn %p (host %s:%d), VBUSYING\n",
                 tcon, afs_inet_ntoa_r(rxr_HostOf(tcon), hoststr),
                  ntohs(rxr_PortOf(tcon))));
        H_UNLOCK;
@@ -2419,7 +2450,7 @@ GetClient(struct rx_connection *tcon, struct client **cp)
     }
     if (rxr_CidOf(tcon) != client->sid || rxr_GetEpoch(tcon) != client->VenusEpoch) {
        ViceLog(0,
-               ("GetClient: tcon %x tcon sid %d client sid %d\n",
+               ("GetClient: tcon %p tcon sid %d client sid %d\n",
                 tcon, rxr_CidOf(tcon), client->sid));
        H_UNLOCK;
        return VBUSY;
@@ -2617,7 +2648,7 @@ h_DumpHost(register struct host *host, int flags, void *rock)
                     ntohs(host->interface->interface[i].port));
            (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
        }
-    sprintf(tmpStr, "] refCount: %d\n", host->refCount);
+    sprintf(tmpStr, "] refCount:%d hostFlags:%hu\n", host->refCount, host->hostFlags);
     (void)STREAM_WRITE(tmpStr, strlen(tmpStr), 1, file);
 
     H_UNLOCK;
@@ -3201,9 +3232,10 @@ h_GetWorkStats(int *nump, int *activep, int *delp, afs_int32 cutofftime)
 {
     register struct host *host;
     register int num = 0, active = 0, del = 0;
+    int count;
 
     H_LOCK;
-    for (host = hostList; host; host = host->next) {
+    for (count = 0, host = hostList; host && count < hostCount; host = host->next, count++) {
        if (!(host->hostFlags & HOSTDELETED)) {
            num++;
            if (host->ActiveCall > cutofftime)
@@ -3212,6 +3244,12 @@ h_GetWorkStats(int *nump, int *activep, int *delp, afs_int32 cutofftime)
                del++;
        }
     }
+    if (count != hostCount) {
+       ViceLog(0, ("h_GetWorkStats found %d of %d hosts\n", count, hostCount));
+    } else if (host != NULL) {
+       ViceLog(0, ("h_GetWorkStats found more than %d hosts\n", hostCount));
+       ShutDownAndCore(PANIC);
+    }
     H_UNLOCK;
     if (nump)
        *nump = num;
@@ -3366,6 +3404,7 @@ h_GetHostNetStats(afs_int32 * a_numHostsP, afs_int32 * a_sameNetOrSubnetP,
 
     register struct host *hostP;       /*Ptr to current host entry */
     register afs_uint32 currAddr_HBO;  /*Curr host addr, host byte order */
+    int count;
 
     /*
      * Clear out the storage pointed to by our parameters.
@@ -3376,7 +3415,7 @@ h_GetHostNetStats(afs_int32 * a_numHostsP, afs_int32 * a_sameNetOrSubnetP,
     *a_diffNetworkP = (afs_int32) 0;
 
     H_LOCK;
-    for (hostP = hostList; hostP; hostP = hostP->next) {
+    for (count = 0, hostP = hostList; hostP && count < hostCount; hostP = hostP->next, count++) {
        if (!(hostP->hostFlags & HOSTDELETED)) {
            /*
             * Bump the number of undeleted host entries found.
@@ -3390,6 +3429,12 @@ h_GetHostNetStats(afs_int32 * a_numHostsP, afs_int32 * a_sameNetOrSubnetP,
                              a_diffNetworkP);
        }                       /*Only look at non-deleted hosts */
     }                          /*For each host record hashed to this index */
+    if (count != hostCount) {
+       ViceLog(0, ("h_GetHostNetStats found %d of %d hosts\n", count, hostCount));
+    } else if (hostP != NULL) {
+       ViceLog(0, ("h_GetHostNetStats found more than %d hosts\n", hostCount));
+       ShutDownAndCore(PANIC);
+    }
     H_UNLOCK;
 }                              /*h_GetHostNetStats */
 
@@ -3431,8 +3476,8 @@ CheckHost(register struct host *host, int flags, void *rock)
     }
     if (host->LastCall < checktime) {
        h_Lock_r(host);
-       host->hostFlags |= HWHO_INPROGRESS;
        if (!(host->hostFlags & HOSTDELETED)) {
+            host->hostFlags |= HWHO_INPROGRESS;
            cb_conn = host->callback_rxcon;
            rx_GetConnection(cb_conn);
            if (host->LastCall < clientdeletetime) {
@@ -3500,8 +3545,8 @@ CheckHost(register struct host *host, int flags, void *rock)
            rx_PutConnection(cb_conn);
            cb_conn=NULL;
            H_LOCK;
+            host->hostFlags &= ~HWHO_INPROGRESS;
        }
-       host->hostFlags &= ~HWHO_INPROGRESS;
        h_Unlock_r(host);
     }
     H_UNLOCK;