afs: Avoid creating unused conns
[openafs.git] / src / afs / afs_server.c
index ac90039..d4893b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
  * afsi_SetServerIPRank
  * afs_GetServer
  * afs_ActivateServer
- * 
+ *
  *
  * Local:
  * HaveCallBacksFrom
  * CheckVLServer
  * afs_SortOneServer
  * afs_SetServerPrefs
- * 
+ *
  */
 #include <afsconfig.h>
 #include "afs/param.h"
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 
 #if !defined(UKERNEL)
-#if !defined(AFS_LINUX20_ENV)
-#include <net/if.h>
-#endif
-#include <netinet/in.h>
+# if !defined(AFS_LINUX20_ENV)
+#  include <net/if.h>
+# endif
+# include <netinet/in.h>
 
-#ifdef AFS_SGI62_ENV
-#include "h/hashing.h"
-#endif
-#if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
-#include <netinet/in_var.h>
-#endif /* AFS_HPUX110_ENV */
-#ifdef AFS_DARWIN60_ENV
-#include <net/if_var.h>
-#endif
+# ifdef AFS_SGI62_ENV
+#  include "h/hashing.h"
+# endif
+# if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
+#  include <netinet/in_var.h>
+# endif /* AFS_HPUX110_ENV */
+# ifdef AFS_DARWIN_ENV
+#  include <net/if_var.h>
+# endif
 #endif /* !defined(UKERNEL) */
 
 #include "afsincludes.h"       /* Afs-based standard headers */
 #include "afs/afs_stats.h"     /* afs statistics */
 #include "rx/rx_multi.h"
 
-#if    defined(AFS_SUN56_ENV)
-#include <inet/led.h>
-#include <inet/common.h>
-#if     defined(AFS_SUN58_ENV)
+#if defined(AFS_SUN5_ENV)
+# include <inet/led.h>
+# include <inet/common.h>
 # include <netinet/ip6.h>
 # define ipif_local_addr ipif_lcl_addr
-#  ifndef V4_PART_OF_V6
+# ifndef V4_PART_OF_V6
 #  define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
-#  endif
 # endif
-#include <inet/ip.h>
+# include <inet/ip.h>
 #endif
 
 /* Exported variables */
 afs_rwlock_t afs_xserver;      /* allocation lock for servers */
-struct server *afs_setTimeHost = 0;    /* last host we used for time */
 struct server *afs_servers[NSERVERS];  /* Hashed by server`s uuid & 1st ip */
 afs_rwlock_t afs_xsrvAddr;     /* allocation lock for srvAddrs */
 struct srvAddr *afs_srvAddrs[NSERVERS];        /* Hashed by server's ip */
@@ -130,9 +127,9 @@ GetUpDownStats(struct server *srv)
 void
 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
 {
-    register struct server *a_serverP = sa->server;
-    register struct srvAddr *sap;
-    osi_timeval_t currTime, *currTimeP;        /*Current time */
+    struct server *a_serverP = sa->server;
+    struct srvAddr *sap;
+    osi_timeval32_t currTime, *currTimeP;      /*Current time */
     afs_int32 downTime;                /*Computed downtime, in seconds */
     struct afs_stats_SrvUpDownInfo *upDownP;   /*Ptr to up/down info record */
 
@@ -153,15 +150,10 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
                return;
            }
        }
-       /* 
+       /*
         * All ips are down we treat the whole server down
         */
        a_serverP->flags |= SRVR_ISDOWN;
-       /*
-        * If this was our time server, search for another time server
-        */
-       if (a_serverP == afs_setTimeHost)
-           afs_setTimeHost = 0;
     } else {
        sa->sa_flags &= ~SRVADDR_ISDOWN;
        /* If any ips are up, the server is also marked up */
@@ -180,7 +172,7 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
      * updated; we'll need them one way or another.
      */
     currTimeP = &currTime;
-    osi_GetuTime(currTimeP);
+    osi_GetTime(currTimeP);
 
     upDownP = GetUpDownStats(a_serverP);
 
@@ -238,20 +230,20 @@ afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
 
 
 afs_int32
-afs_ServerDown(struct srvAddr *sa)
+afs_ServerDown(struct srvAddr *sa, int code, struct rx_connection *rxconn)
 {
-    register struct server *aserver = sa->server;
+    struct server *aserver = sa->server;
 
     AFS_STATCNT(ServerDown);
-    if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN) 
+    if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
        return 0;
     afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
     if (sa->sa_portal == aserver->cell->vlport)
-       print_internet_address
-           ("afs: Lost contact with volume location server ", sa, "", 1);
+       print_internet_address("afs: Lost contact with volume location server ",
+                             sa, "", 1, code, rxconn);
     else
        print_internet_address("afs: Lost contact with file server ", sa, "",
-                              1);
+                              1, code, rxconn);
     return 1;
 }                              /*ServerDown */
 
@@ -260,9 +252,9 @@ afs_ServerDown(struct srvAddr *sa)
 int
 afs_HaveCallBacksFrom(struct server *aserver)
 {
-    register afs_int32 now;
-    register int i;
-    register struct vcache *tvc;
+    afs_int32 now;
+    int i;
+    struct vcache *tvc;
 
     AFS_STATCNT(HaveCallBacksFrom);
     now = osi_Time();          /* for checking for expired callbacks */
@@ -283,11 +275,12 @@ afs_HaveCallBacksFrom(struct server *aserver)
 
 
 static void
-CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
+CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
 {
-    register struct server *aserver = sa->server;
-    register struct afs_conn *tc;
-    register afs_int32 code;
+    struct server *aserver = sa->server;
+    struct afs_conn *tc;
+    afs_int32 code;
+    struct rx_connection *rxconn;
 
     AFS_STATCNT(CheckVLServer);
     /* Ping dead servers to see if they're back */
@@ -298,36 +291,37 @@ CheckVLServer(register struct srvAddr *sa, struct vrequest *areq)
        return;                 /* can't do much */
 
     tc = afs_ConnByHost(aserver, aserver->cell->vlport,
-                       aserver->cell->cellNum, areq, 1, SHARED_LOCK);
+                       aserver->cell->cellNum, areq, 1, SHARED_LOCK, 0,
+                       &rxconn);
     if (!tc)
        return;
-    rx_SetConnDeadTime(tc->id, 3);
+    rx_SetConnDeadTime(rxconn, 3);
 
     RX_AFS_GUNLOCK();
-    code = VL_ProbeServer(tc->id);
+    code = VL_ProbeServer(rxconn);
     RX_AFS_GLOCK();
-    rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
-    afs_PutConn(tc, SHARED_LOCK);
+    rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
     /*
      * If probe worked, or probe call not yet defined (for compatibility
      * with old vlsevers), then we treat this server as running again
      */
     if (code == 0 || (code <= -450 && code >= -470)) {
-       if (tc->srvr == sa) {
+       if (tc->parent->srvr == sa) {
            afs_MarkServerUpOrDown(sa, 0);
            print_internet_address("afs: volume location server ", sa,
-                                  " is back up", 2);
+                                  " is back up", 2, code, rxconn);
        }
     }
+    afs_PutConn(tc, rxconn, SHARED_LOCK);
 
 }                              /*CheckVLServer */
 
 
 #ifndef        AFS_MINCHANGE           /* So that some can increase it in param.h */
-#define AFS_MINCHANGE 2                /* min change we'll bother with */
+# define AFS_MINCHANGE 2               /* min change we'll bother with */
 #endif
 #ifndef AFS_MAXCHANGEBACK
-#define AFS_MAXCHANGEBACK 10   /* max seconds we'll set a clock back at once */
+# define AFS_MAXCHANGEBACK 10  /* max seconds we'll set a clock back at once */
 #endif
 
 
@@ -360,8 +354,8 @@ afs_CountServers(void)
     int currIdx;               /*Curr idx into srv table */
     struct server *currSrvP;   /*Ptr to curr server record */
     afs_int32 currChainLen;    /*Length of curr hash chain */
-    osi_timeval_t currTime;    /*Current time */
-    osi_timeval_t *currTimeP;  /*Ptr to above */
+    osi_timeval32_t currTime;  /*Current time */
+    osi_timeval32_t *currTimeP;        /*Ptr to above */
     afs_int32 srvRecordAge;    /*Age of server record, in secs */
     struct afs_stats_SrvUpDownInfo *upDownP;   /*Ptr to current up/down
                                                 * info being manipulated */
@@ -381,32 +375,32 @@ afs_CountServers(void)
     afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
     afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
     afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
-    memset((char *)afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
+    memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
           AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
 
     afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
     afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
     afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
-    memset((char *)afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
+    memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
           AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
 
     afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
     afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
     afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
-    memset((char *)afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
+    memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
           AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
 
     afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
     afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
     afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
-    memset((char *)afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
+    memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
           AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
 
     /*
      * Compute the current time, used to figure out server record ages.
      */
     currTimeP = &currTime;
-    osi_GetuTime(currTimeP);
+    osi_GetTime(currTimeP);
 
     /*
      * Sweep the server hash table, tallying all we need to know.
@@ -422,7 +416,7 @@ afs_CountServers(void)
 
            /*
             * Any further tallying for this record will only be done if it has
-            * been activated. 
+            * been activated.
             */
            if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
                && currSrvP->addr && currSrvP->cell) {
@@ -487,7 +481,7 @@ afs_CountServers(void)
 
 
 void
-ForceAllNewConnections()
+ForceAllNewConnections(void)
 {
     int srvAddrCount;
     struct srvAddr **addrs;
@@ -505,6 +499,7 @@ ForceAllNewConnections()
     }
 
     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
+    osi_Assert(addrs != NULL);
     j = 0;
     for (i = 0; i < NSERVERS; i++) {
        for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
@@ -520,44 +515,138 @@ ForceAllNewConnections()
         sa = addrs[i];
        ForceNewConnections(sa);
     }
+
+    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
+}
+
+static void
+CkSrv_MarkUpDown(struct afs_conn **conns, struct rx_connection **rxconns,
+                 int nconns, afs_int32 *results)
+{
+    struct srvAddr *sa;
+    struct afs_conn *tc;
+    afs_int32 i;
+
+    for(i = 0; i < nconns; i++){
+       tc = conns[i];
+       sa = tc->parent->srvr;
+
+       if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
+           (tc->parent->srvr == sa)) {
+           /* server back up */
+           print_internet_address("afs: file server ", sa, " is back up", 2,
+                                  results[i], rxconns[i]);
+
+           ObtainWriteLock(&afs_xserver, 244);
+           ObtainWriteLock(&afs_xsrvAddr, 245);
+           afs_MarkServerUpOrDown(sa, 0);
+           ReleaseWriteLock(&afs_xsrvAddr);
+           ReleaseWriteLock(&afs_xserver);
+
+           if (afs_waitForeverCount) {
+               afs_osi_Wakeup(&afs_waitForever);
+           }
+       } else {
+           if (results[i] < 0) {
+               /* server crashed */
+               afs_ServerDown(sa, results[i], rxconns[i]);
+               ForceNewConnections(sa);  /* multi homed clients */
+           }
+       }
+    }
+}
+
+void
+CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
+             struct afs_conn **conns)
+{
+    Capabilities *caps;
+    afs_int32 *results;
+    afs_int32 i;
+    struct server *ts;
+
+    caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
+    osi_Assert(caps != NULL);
+    memset(caps, 0, nconns * sizeof(Capabilities));
+
+    results = afs_osi_Alloc(nconns * sizeof (afs_int32));
+    osi_Assert(results != NULL);
+
+    AFS_GUNLOCK();
+    multi_Rx(rxconns,nconns)
+      {
+       multi_RXAFS_GetCapabilities(&caps[multi_i]);
+       results[multi_i] = multi_error;
+      } multi_End;
+    AFS_GLOCK();
+
+    for ( i = 0 ; i < nconns ; i++ ) {
+       ts = conns[i]->parent->srvr->server;
+       if ( !ts )
+           continue;
+       ts->capabilities = 0;
+       ts->flags |= SCAPS_KNOWN;
+       if ( results[i] == RXGEN_OPCODE ) {
+           /* Mark server as up - it responded */
+           results[i] = 0;
+           continue;
+       }
+       if ( results[i] >= 0 )
+           /* we currently handle 32-bits of capabilities */
+           if (caps[i].Capabilities_len > 0) {
+               ts->capabilities = caps[i].Capabilities_val[0];
+               xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
+               caps[i].Capabilities_val = NULL;
+               caps[i].Capabilities_len = 0;
+           }
+    }
+    CkSrv_MarkUpDown(conns, rxconns, nconns, results);
+
+    afs_osi_Free(caps, nconns * sizeof(Capabilities));
+    afs_osi_Free(results, nconns * sizeof(afs_int32));
 }
 
 /* check down servers (if adown), or running servers (if !adown) */
 void
 afs_CheckServers(int adown, struct cell *acellp)
 {
-    struct vrequest treq;
+    afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
+}
+
+/* adown: AFS_LS_UP   - check only up
+ *        AFS_LS_DOWN - check only down.
+ *        AFS_LS_ALL  - check all */
+void
+afs_LoopServers(int adown, struct cell *acellp, int vlalso,
+               void (*func1) (int nservers, struct rx_connection **rxconns,
+                              struct afs_conn **conns),
+               void (*func2) (int nservers, struct rx_connection **rxconns,
+                              struct afs_conn **conns))
+{
+    struct vrequest *treq = NULL;
     struct server *ts;
     struct srvAddr *sa;
-    struct afs_conn *tc;
+    struct afs_conn *tc = NULL;
     afs_int32 i, j;
     afs_int32 code;
-    afs_int32 start, end = 0, delta;
-    osi_timeval_t tv;
     struct unixuser *tu;
-    char tbuffer[CVBS];
     int srvAddrCount;
     struct srvAddr **addrs;
     struct afs_conn **conns;
     int nconns;
-    struct rx_connection **rxconns;      
-    afs_int32 *conntimer, *deltas, *results;
+    struct rx_connection **rxconns;
+    afs_int32 *conntimer;
 
     AFS_STATCNT(afs_CheckServers);
 
-    /* 
+    /*
      * No sense in doing the server checks if we are running in disconnected
      * mode
      */
     if (AFS_IS_DISCONNECTED)
         return;
 
-    conns = (struct afs_conn **)0;
-    rxconns = (struct rx_connection **) 0;
-    conntimer = 0;
-    nconns = 0;
-
-    if ((code = afs_InitReq(&treq, afs_osi_credp)))
+    if ((code = afs_CreateReq(&treq, afs_osi_credp)))
        return;
     ObtainReadLock(&afs_xserver);      /* Necessary? */
     ObtainReadLock(&afs_xsrvAddr);
@@ -570,6 +659,7 @@ afs_CheckServers(int adown, struct cell *acellp)
     }
 
     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
+    osi_Assert(addrs != NULL);
     j = 0;
     for (i = 0; i < NSERVERS; i++) {
        for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
@@ -582,14 +672,16 @@ afs_CheckServers(int adown, struct cell *acellp)
     ReleaseReadLock(&afs_xsrvAddr);
     ReleaseReadLock(&afs_xserver);
 
-    conns = (struct afs_conn **)afs_osi_Alloc(j * sizeof(struct afs_conn *));
-    rxconns = (struct rx_connection **)afs_osi_Alloc(j * sizeof(struct rx_connection *));
-    conntimer = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
-    deltas = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
-    results = (afs_int32 *)afs_osi_Alloc(j * sizeof (afs_int32));
+    conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
+    osi_Assert(conns != NULL);
+    rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
+    osi_Assert(rxconns != NULL);
+    conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
+    osi_Assert(conntimer != NULL);
 
+    nconns = 0;
     for (i = 0; i < j; i++) {
-       deltas[i] = 0;
+       struct rx_connection *rxconn;
        sa = addrs[i];
        ts = sa->server;
        if (!ts)
@@ -601,161 +693,66 @@ afs_CheckServers(int adown, struct cell *acellp)
        if (acellp && acellp != ts->cell)
            continue;
 
-       if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
-           || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
+       if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
+           || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
            continue;
 
        /* check vlserver with special code */
        if (sa->sa_portal == AFS_VLPORT) {
-           CheckVLServer(sa, &treq);
+           if (vlalso)
+               CheckVLServer(sa, treq);
            continue;
        }
 
        if (!ts->cell)          /* not really an active server, anyway, it must */
            continue;           /* have just been added by setsprefs */
 
+       if ((sa->sa_flags & SRVADDR_ISDOWN) == 0 && !afs_HaveCallBacksFrom(sa->server)) {
+           /* Server is up, and we have no active callbacks from it. */
+           continue;
+       }
+
        /* get a connection, even if host is down; bumps conn ref count */
-       tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
+       tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
        tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
-                         1 /*force */ , 1 /*create */ , SHARED_LOCK);
+                         1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
+                         &rxconn);
        afs_PutUser(tu, SHARED_LOCK);
        if (!tc)
            continue;
 
-       if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
-           || (tc->srvr->server == afs_setTimeHost)) {
-           conns[nconns]=tc; 
-           rxconns[nconns]=tc->id;
-           if (sa->sa_flags & SRVADDR_ISDOWN) {
-               rx_SetConnDeadTime(tc->id, 3);
-               conntimer[nconns]=1;
-           } else {
-               conntimer[nconns]=0;
-           }
-           nconns++;
+       conns[nconns]=tc;
+       rxconns[nconns]=rxconn;
+       if (sa->sa_flags & SRVADDR_ISDOWN) {
+           rx_SetConnDeadTime(rxconn, 3);
+           conntimer[nconns]=1;
+       } else {
+           conntimer[nconns]=0;
        }
+       nconns++;
+
     } /* Outer loop over addrs */
 
-    start = osi_Time();         /* time the gettimeofday call */
-    AFS_GUNLOCK(); 
-    multi_Rx(rxconns,nconns)
-      {
-       tv.tv_sec = tv.tv_usec = 0;
-       multi_RXAFS_GetTime((afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
-       tc = conns[multi_i];
-       sa = tc->srvr;
-       if (conntimer[multi_i] == 1)
-         rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
-       end = osi_Time();
-       results[multi_i]=multi_error;
-       if ((start == end) && !multi_error)
-         deltas[multi_i] = end - tv.tv_sec;
-       
-      } multi_End;
-    AFS_GLOCK(); 
-    
-    for(i=0;i<nconns;i++){
-      tc = conns[i];
-      sa = tc->srvr;
-      
-      if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
-       /* server back up */
-       print_internet_address("afs: file server ", sa, " is back up", 2);
-       
-       ObtainWriteLock(&afs_xserver, 244);
-       ObtainWriteLock(&afs_xsrvAddr, 245);        
-       afs_MarkServerUpOrDown(sa, 0);
-       ReleaseWriteLock(&afs_xsrvAddr);
-       ReleaseWriteLock(&afs_xserver);
-       
-       if (afs_waitForeverCount) {
-         afs_osi_Wakeup(&afs_waitForever);
-       }
-      } else {
-       if (results[i] < 0) {
-         /* server crashed */
-         afs_ServerDown(sa);
-         ForceNewConnections(sa);  /* multi homed clients */
-       }
-      }
-    }
+    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
+    addrs = NULL;
 
-    /*
-     * If we're supposed to set the time, and the call worked
-     * quickly (same second response) and this is the host we
-     * use for the time and the time is really different, then
-     * really set the time
-     */
-    if (afs_setTime != 0) {
-       for (i=0; i<nconns; i++) {
-           delta = deltas[i];
-           tc = conns[i];
-           sa = tc->srvr;
-           
-           if ((tc->srvr->server == afs_setTimeHost ||
-                /* Sync only to a server in the local cell */
-                (afs_setTimeHost == (struct server *)0 &&
-                 afs_IsPrimaryCell(sa->server->cell)))) {
-               /* set the time */
-               char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
-               delta = end - tv.tv_sec;   /* how many secs fast we are */
-               
-               afs_setTimeHost = tc->srvr->server;
-               /* see if clock has changed enough to make it worthwhile */
-               if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
-                   end = osi_Time();
-                   if (delta > AFS_MAXCHANGEBACK) {
-                       /* setting clock too far back, just do it a little */
-                       tv.tv_sec = end - AFS_MAXCHANGEBACK;
-                   } else {
-                       tv.tv_sec = end - delta;
-                   }
-                   afs_osi_SetTime(&tv);
-                   if (delta > 0) {
-                       strcpy(msgbuf, "afs: setting clock back ");
-                       if (delta > AFS_MAXCHANGEBACK) {
-                           afs_strcat(msgbuf, 
-                                      afs_cv2string(&tbuffer[CVBS], 
-                                                    AFS_MAXCHANGEBACK));
-                           afs_strcat(msgbuf, " seconds (of ");
-                           afs_strcat(msgbuf, 
-                                      afs_cv2string(&tbuffer[CVBS], 
-                                                    delta - 
-                                                    AFS_MAXCHANGEBACK));
-                           afs_strcat(msgbuf, ", via ");
-                           print_internet_address(msgbuf, sa, 
-                                                  "); clock is still fast.",
-                                                  0);
-                       } else {
-                           afs_strcat(msgbuf, 
-                                      afs_cv2string(&tbuffer[CVBS], delta));
-                           afs_strcat(msgbuf, " seconds (via ");
-                           print_internet_address(msgbuf, sa, ").", 0);
-                       }
-                   } else {
-                       strcpy(msgbuf, "afs: setting clock ahead ");
-                       afs_strcat(msgbuf, 
-                                  afs_cv2string(&tbuffer[CVBS], -delta));
-                       afs_strcat(msgbuf, " seconds (via ");
-                       print_internet_address(msgbuf, sa, ").", 0);
-                   }
-                    /* We're only going to set it once; why bother looping? */
-                   break; 
-               }
-           }
-       }
+    (*func1)(nconns, rxconns, conns);
+
+    if (func2) {
+       (*func2)(nconns, rxconns, conns);
     }
+
     for (i = 0; i < nconns; i++) {
-       afs_PutConn(conns[i], SHARED_LOCK);     /* done with it now */
+       if (conntimer[i] == 1)
+           rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
+       afs_PutConn(conns[i], rxconns[i], SHARED_LOCK);     /* done with it now */
     }
-    
-    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
+
     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
     afs_osi_Free(conntimer, j * sizeof(afs_int32));
-    afs_osi_Free(deltas, j * sizeof(afs_int32));
-    afs_osi_Free(results, j * sizeof(afs_int32));
-    
+    afs_DestroyReq(treq);
+
 } /*afs_CheckServers*/
 
 
@@ -802,19 +799,19 @@ afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
 
 /* Rules:
    X = (aX + c) % m
-   m is a power of two 
+   m is a power of two
    a % 8 is 5
    a is 0.73m  should be 0.01m .. 0.99m
    c is more or less immaterial.  1 or a is suggested.
-  
+
 NB:  LOW ORDER BITS are not very random.  To get small random numbers,
-     treat result as <1, with implied binary point, and multiply by 
+     treat result as <1, with implied binary point, and multiply by
      desired modulus.
 NB:  Has to be unsigned, since shifts on signed quantities may preserve
      the sign bit.
 */
-/* added rxi_getaddr() to try to get as much initial randomness as 
-   possible, since at least one customer reboots ALL their clients 
+/* added rxi_getaddr() to try to get as much initial randomness as
+   possible, since at least one customer reboots ALL their clients
    simultaneously -- so osi_Time is bound to be the same on some of the
    clients.  This is probably OK, but I don't want to see too much of it.
 */
@@ -825,17 +822,19 @@ unsigned int
 afs_random(void)
 {
     static afs_int32 state = 0;
-    register int i;
+    int i;
 
     AFS_STATCNT(afs_random);
     if (!state) {
-       osi_timeval_t t;
+       osi_timeval32_t t;
        osi_GetTime(&t);
        /*
-        * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
-        * bits are in a tv_usec
+        * Clear the low nybble of tv_usec in a size-independent manner before adding
+        * in the rest of the state.
         */
-       state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
+       state = t.tv_usec;
+       state ^= (state & 0x0f);
+       state += rxi_getaddr() & 0xff;
        state += (t.tv_sec & 0xff);
        for (i = 0; i < 30; i++) {
            ranstage(state);
@@ -850,7 +849,7 @@ afs_random(void)
 /* returns int 0..14 using the high bits of a pseudo-random number instead of
    the low bits, as the low bits are "less random" than the high ones...
    slight roundoff error exists, an excercise for the reader.
-   need to multiply by something with lots of ones in it, so multiply by 
+   need to multiply by something with lots of ones in it, so multiply by
    8 or 16 is right out.
  */
 int
@@ -939,7 +938,7 @@ afs_SortServers(struct server *aservers[], int count)
 }                              /*afs_SortServers */
 
 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
-   data structures to determine what the local IP addresses and subnet masks 
+   data structures to determine what the local IP addresses and subnet masks
    are in order to choose which server(s) are on the local subnet.
 
    As I see it, there are several cases:
@@ -951,19 +950,19 @@ afs_SortServers(struct server *aservers[], int count)
    4. The server is on a different logical subnet or net than this host, but
    this host is a 'metric 0 gateway' to it.  Ie, two address-spaces share
    one physical medium.
-   5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the 
+   5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
    server.
    6. This host and the server are disjoint.
 
    That is a rough order of preference.  If a point-to-point link has a high
-   metric, I'm assuming that it is a very slow link, and putting it at the 
-   bottom of the list (at least until RX works better over slow links).  If 
-   its metric is 1, I'm assuming that it's relatively fast (T1) and putting 
+   metric, I'm assuming that it is a very slow link, and putting it at the
+   bottom of the list (at least until RX works better over slow links).  If
+   its metric is 1, I'm assuming that it's relatively fast (T1) and putting
    it ahead of #6.
    It's not easy to check for case #4, so I'm ignoring it for the time being.
 
    BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
-   That could be used to prefer certain servers fairly easily.  Maybe some 
+   That could be used to prefer certain servers fairly easily.  Maybe some
    other time...
 
    NOTE: this code is very system-dependent, and very dependent on the TCP/IP
@@ -983,117 +982,15 @@ afs_SortServers(struct server *aservers[], int count)
 
 #define        USEIFADDR
 
-
-#if    defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
-#include <inet/common.h>
-/* IP interface structure, one per local address */
-typedef struct ipif_s {
-     /**/ struct ipif_s *ipif_next;
-    struct ill_s *ipif_ill;    /* Back pointer to our ill */
-    long ipif_id;              /* Logical unit number */
-    u_int ipif_mtu;            /* Starts at ipif_ill->ill_max_frag */
-    afs_int32 ipif_local_addr; /* Local IP address for this if. */
-    afs_int32 ipif_net_mask;   /* Net mask for this interface. */
-    afs_int32 ipif_broadcast_addr;     /* Broadcast addr for this interface. */
-    afs_int32 ipif_pp_dst_addr;        /* Point-to-point dest address. */
-    u_int ipif_flags;          /* Interface flags. */
-    u_int ipif_metric;         /* BSD if metric, for compatibility. */
-    u_int ipif_ire_type;       /* LOCAL or LOOPBACK */
-    mblk_t *ipif_arp_down_mp;  /* Allocated at time arp comes up to
-                                * prevent awkward out of mem condition
-                                * later
-                                */
-    mblk_t *ipif_saved_ire_mp; /* Allocated for each extra IRE_SUBNET/
-                                * RESOLVER on this interface so that
-                                * they can survive ifconfig down.
-                                */
-    /*
-     * The packet counts in the ipif contain the sum of the
-     * packet counts in dead IREs that were affiliated with
-     * this ipif.
-     */
-    u_long ipif_fo_pkt_count;  /* Forwarded thru our dead IREs */
-    u_long ipif_ib_pkt_count;  /* Inbound packets for our dead IREs */
-    u_long ipif_ob_pkt_count;  /* Outbound packets to our dead IREs */
-    unsigned int
-      ipif_multicast_up:1,     /* We have joined the allhosts group */
-    : 0;
-} ipif_t;
-
-typedef struct ipfb_s {
-     /**/ struct ipf_s *ipfb_ipf;      /* List of ... */
-    kmutex_t ipfb_lock;                /* Protect all ipf in list */
-} ipfb_t;
-
-typedef struct ilm_s {
-     /**/ afs_int32 ilm_addr;
-    int ilm_refcnt;
-    u_int ilm_timer;           /* IGMP */
-    struct ipif_s *ilm_ipif;   /* Back pointer to ipif */
-    struct ilm_s *ilm_next;    /* Linked list for each ill */
-} ilm_t;
-
-typedef struct ill_s {
-     /**/ struct ill_s *ill_next;      /* Chained in at ill_g_head. */
-    struct ill_s **ill_ptpn;   /* Pointer to previous next. */
-    queue_t *ill_rq;           /* Read queue. */
-    queue_t *ill_wq;           /* Write queue. */
-
-    int ill_error;             /* Error value sent up by device. */
-
-    ipif_t *ill_ipif;          /* Interface chain for this ILL. */
-    u_int ill_ipif_up_count;   /* Number of IPIFs currently up. */
-    u_int ill_max_frag;                /* Max IDU. */
-    char *ill_name;            /* Our name. */
-    u_int ill_name_length;     /* Name length, incl. terminator. */
-    u_int ill_subnet_type;     /* IRE_RESOLVER or IRE_SUBNET. */
-    u_int ill_ppa;             /* Physical Point of Attachment num. */
-    u_long ill_sap;
-    int ill_sap_length;                /* Including sign (for position) */
-    u_int ill_phys_addr_length;        /* Excluding the sap. */
-    mblk_t *ill_frag_timer_mp; /* Reassembly timer state. */
-    ipfb_t *ill_frag_hash_tbl; /* Fragment hash list head. */
-
-    queue_t *ill_bind_pending_q;       /* Queue waiting for DL_BIND_ACK. */
-    ipif_t *ill_ipif_pending;  /* IPIF waiting for DL_BIND_ACK. */
-
-    /* ill_hdr_length and ill_hdr_mp will be non zero if
-     * the underlying device supports the M_DATA fastpath
-     */
-    int ill_hdr_length;
-
-    ilm_t *ill_ilm;            /* Multicast mebership for lower ill */
-
-    /* All non-nil cells between 'ill_first_mp_to_free' and
-     * 'ill_last_mp_to_free' are freed in ill_delete.
-     */
-#define        ill_first_mp_to_free    ill_hdr_mp
-    mblk_t *ill_hdr_mp;                /* Contains fastpath template */
-    mblk_t *ill_bcast_mp;      /* DLPI header for broadcasts. */
-    mblk_t *ill_bind_pending;  /* T_BIND_REQ awaiting completion. */
-    mblk_t *ill_resolver_mp;   /* Resolver template. */
-    mblk_t *ill_attach_mp;
-    mblk_t *ill_bind_mp;
-    mblk_t *ill_unbind_mp;
-    mblk_t *ill_detach_mp;
-#define        ill_last_mp_to_free     ill_detach_mp
-
-    u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
-       ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
-      MI_HRT_DCL(ill_rtime)
-      MI_HRT_DCL(ill_rtmp)
-} ill_t;
-#endif
-
 #ifdef AFS_USERSPACE_IP_ADDR
-#ifndef afs_min
-#define afs_min(A,B) ((A)<(B)) ? (A) : (B)
-#endif
+# ifndef afs_min
+#  define afs_min(A,B) ((A)<(B)) ? (A) : (B)
+# endif
 /*
  * The IP addresses and ranks are determined by afsd (in user space) and
  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
- * system call. These are stored in the data structure 
- * called 'afs_cb_interface'. 
+ * system call. These are stored in the data structure
+ * called 'afs_cb_interface'.
  *
  * struct srvAddr *sa;         remote server
  * afs_int32 addr;                one of my local addr in net order
@@ -1136,8 +1033,10 @@ afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
     }
     return;
 }
+
 #else /* AFS_USERSPACE_IP_ADDR */
-#if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
+
+# if !defined(AFS_SUN5_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_OBSD47_ENV) && !defined(AFS_FBSD_ENV) && defined(USEIFADDR)
 void
 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
 {
@@ -1160,7 +1059,7 @@ afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
                sa->sa_iprank = t;
        }
     }
-#ifdef  IFF_POINTTOPOINT
+#  if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
     /* check for case #4 -- point-to-point link */
     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
        && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
@@ -1171,50 +1070,48 @@ afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
        if (sa->sa_iprank > t)
            sa->sa_iprank = t;
     }
-#endif /* IFF_POINTTOPOINT */
+#  endif /* IFF_POINTOPOINT */
 }
-#endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#if defined(AFS_DARWIN60_ENV) && defined(USEIFADDR)
-#ifndef afs_min
-#define afs_min(A,B) ((A)<(B)) ? (A) : (B)
-#endif
+# endif /* !SUN5 && !DARWIN && !OBSD47 && !FBSD && USEIFADDR */
+# if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV) || defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
+#  ifndef afs_min
+#   define afs_min(A,B) ((A)<(B)) ? (A) : (B)
+#  endif
 void
-afsi_SetServerIPRank(sa, ifa)
-     struct srvAddr *sa;
-#ifdef AFS_DARWIN80_ENV
-     ifaddr_t ifa;
-#else
-     struct ifaddr *ifa;
-#endif
+afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
 {
     struct sockaddr sout;
     struct sockaddr_in *sin;
+#  if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
     int t;
+#  else
+    void *t;
+#  endif
 
     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
     afs_uint32 serverAddr;
 
-    if (ifaddr_address_family(ifa) != AF_INET)
+    if (rx_ifaddr_address_family(ifa) != AF_INET)
        return;
-    t = ifaddr_address(ifa, &sout, sizeof(sout));
-    if (t == 0) {
+    t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
+    if (t != 0) {
        sin = (struct sockaddr_in *)&sout;
        myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
     } else {
        myAddr = 0;
     }
     serverAddr = ntohl(sa->sa_ip);     /* server's IP addr in host order */
-    t = ifaddr_netmask(ifa, &sout, sizeof(sout));
-    if (t == 0) {
+    t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
+    if (t != 0) {
        sin = (struct sockaddr_in *)&sout;
        subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
     } else {
        subnetmask = 0;
     }
-    t = ifaddr_dstaddress(ifa, &sout, sizeof(sout));
-    if (t == 0) {
+    t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
+    if (t != 0) {
        sin = (struct sockaddr_in *)&sout;
-       myDstaddr = sin->sin_addr.s_addr;
+       myDstaddr = ntohl(sin->sin_addr.s_addr);
     } else {
        myDstaddr = 0;
     }
@@ -1236,39 +1133,41 @@ afsi_SetServerIPRank(sa, ifa)
            if (serverAddr == myAddr) { /* same machine */
                sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
            } else {            /* same subnet */
-               sa->sa_iprank = afs_min(sa->sa_iprank, HI + ifnet_metric(ifaddr_ifnet(ifa)));
+               sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
            }
        } else {                /* same net */
-           sa->sa_iprank = afs_min(sa->sa_iprank, MED + ifnet_metric(ifaddr_ifnet(ifa)));
+           sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
        }
     }
-#ifdef  IFF_POINTTOPOINT
+#  ifdef  IFF_POINTTOPOINT
     /* check for case #4 -- point-to-point link */
-    if ((ifnet_flags(ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
+    if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
        && (myDstaddr == serverAddr)) {
-       if (ifnet_metric(ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
+       if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
            t = MAXDEFRANK;
        else
-           t = MED + (PPWEIGHT << ifnet_metric(ifaddr_ifnet(ifa)));
+           t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
        if (sa->sa_iprank > t)
            sa->sa_iprank = t;
        }
-#endif /* IFF_POINTTOPOINT */
+#  endif /* IFF_POINTTOPOINT */
 }
-#endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
-#endif /* else AFS_USERSPACE_IP_ADDR */
+# endif /* (DARWIN || OBSD47 || FBSD) && USEIFADDR */
+#endif /* AFS_USERSPACE_IP_ADDR */
 
 #ifdef AFS_SGI62_ENV
 static int
-
-  afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
-                    caddr_t arg2) {
+afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
+                  caddr_t arg2)
+{
     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
     return 0;                  /* Never match, so we enumerate everyone */
 }
 #endif                         /* AFS_SGI62_ENV */
-static int afs_SetServerPrefs(struct srvAddr *sa) {
-#if     defined(AFS_USERSPACE_IP_ADDR)
+static int
+afs_SetServerPrefs(struct srvAddr *const sa)
+{
+#if defined(AFS_USERSPACE_IP_ADDR)
     int i;
 
       sa->sa_iprank = LO;
@@ -1277,20 +1176,19 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
                             afs_cb_interface.subnetmask[i]);
     }
 #else                          /* AFS_USERSPACE_IP_ADDR */
-#if    defined(AFS_SUN5_ENV)
-#ifdef AFS_SUN510_ENV
+# if defined(AFS_SUN5_ENV)
+#  ifdef AFS_SUN510_ENV
     int i = 0;
-#else
+#  else
     extern struct ill_s *ill_g_headp;
     long *addr = (long *)ill_g_headp;
     ill_t *ill;
     ipif_t *ipif;
-#endif
+#  endif
     int subnet, subnetmask, net, netmask;
 
-    if (sa)
-         sa->sa_iprank = 0;
-#ifdef AFS_SUN510_ENV
+    sa->sa_iprank = 0;
+#  ifdef AFS_SUN510_ENV
     rw_enter(&afsifinfo_lock, RW_READER);
 
     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
@@ -1306,16 +1204,6 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
        }
        net = afsifinfo[i].ipaddr & netmask;
 
-#ifdef notdef
-       if (!s) {
-           if (afsifinfo[i].ipaddr != 0x7f000001) {    /* ignore loopback */
-               *cnt += 1;
-               if (*cnt > 16)
-                   return;
-               *addrp++ = afsifinfo[i].ipaddr;
-           }
-       } else
-#endif /* notdef */
         {
             /* XXXXXX Do the individual ip ranking below XXXXX */
             if ((sa->sa_ip & netmask) == net) {
@@ -1342,21 +1230,21 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
             }
         }
     }
-    
+
     rw_exit(&afsifinfo_lock);
-#else
+
+#  else /* AFS_SUN510_ENV */
+
     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
         ill = ill->ill_next) {
-#ifdef AFS_SUN58_ENV
        /* Make sure this is an IPv4 ILL */
        if (ill->ill_isv6)
            continue;
-#endif
        for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
            subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
            subnetmask = ipif->ipif_net_mask;
            /*
-            * Generate the local net using the local address and 
+            * Generate the local net using the local address and
             * whate we know about Class A, B and C networks.
             */
            if (IN_CLASSA(ipif->ipif_local_addr)) {
@@ -1369,16 +1257,6 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
                netmask = 0;
            }
            net = ipif->ipif_local_addr & netmask;
-#ifdef notdef
-           if (!s) {
-               if (ipif->ipif_local_addr != 0x7f000001) {      /* ignore loopback */
-                   *cnt += 1;
-                   if (*cnt > 16)
-                       return;
-                   *addrp++ = ipif->ipif_local_addr;
-               }
-           } else
-#endif /* notdef */
            {
                /* XXXXXX Do the individual ip ranking below XXXXX */
                if ((sa->sa_ip & netmask) == net) {
@@ -1406,55 +1284,36 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
            }
        }
     }
-#endif /* AFS_SUN510_ENV */
-#else
-#ifndef USEIFADDR
-    struct ifnet *ifn = NULL;
+#  endif /* AFS_SUN510_ENV */
+# else /* AFS_SUN5_ENV */
+#  ifndef USEIFADDR
+    rx_ifnet_t ifn = NULL;
     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
     struct sockaddr_in *sin;
 
-    if (!sa) {
-#ifdef notdef                  /* clean up, remove this */
-       for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
-           for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
-               if ((IFADDR2SA(ifad)->sa_family == AF_INET)
-                   && !(ifn->if_flags & IFF_LOOPBACK)) {
-                   *cnt += 1;
-                   if (*cnt > 16)
-                       return;
-                   *addrp++ =
-                       ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
-                       s_addr;
-               }
-       }}
-#endif                         /* notdef */
-       return;
-    }
     sa->sa_iprank = 0;
-#ifdef ADAPT_MTU
     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
-#endif
     if (ifn) {                 /* local, more or less */
-#ifdef IFF_LOOPBACK
+#   ifdef IFF_LOOPBACK
        if (ifn->if_flags & IFF_LOOPBACK) {
            sa->sa_iprank = TOPR;
            goto end;
        }
-#endif /* IFF_LOOPBACK */
+#   endif /* IFF_LOOPBACK */
        sin = (struct sockaddr_in *)IA_SIN(ifad);
        if (SA2ULONG(sin) == sa->sa_ip) {
            sa->sa_iprank = TOPR;
            goto end;
        }
-#ifdef IFF_BROADCAST
+#   ifdef IFF_BROADCAST
        if (ifn->if_flags & IFF_BROADCAST) {
            if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
                sa->sa_iprank = HI;
                goto end;
            }
        }
-#endif /* IFF_BROADCAST */
-#ifdef IFF_POINTOPOINT
+#   endif /* IFF_BROADCAST */
+#   ifdef IFF_POINTOPOINT
        if (ifn->if_flags & IFF_POINTOPOINT) {
            if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
                if (ifn->if_metric > 4) {
@@ -1464,27 +1323,26 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
                    sa->sa_iprank = ifn->if_metric;
            }
        }
-#endif /* IFF_POINTOPOINT */
+#   endif /* IFF_POINTOPOINT */
        sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
     }
-#else                          /* USEIFADDR */
+#  else /* USEIFADDR */
 
-    if (sa)
-       sa->sa_iprank = LO;
-#ifdef AFS_SGI62_ENV
+    sa->sa_iprank = LO;
+#   ifdef AFS_SGI62_ENV
     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
                    (caddr_t) sa, NULL);
-#elif defined(AFS_DARWIN80_ENV)
+#   elif defined(AFS_DARWIN80_ENV)
     {
        errno_t t;
        unsigned int count;
        int cnt=0, m, j;
-       ifaddr_t *ifads;
-       ifnet_t *ifn;
+       rx_ifaddr_t *ifads;
+       rx_ifnet_t *ifns;
 
-       if (!ifnet_list_get(AF_INET, &ifn, &count)) {
+       if (!ifnet_list_get(AF_INET, &ifns, &count)) {
            for (m = 0; m < count; m++) {
-               if (!ifnet_get_address_list(ifn[m], &ifads)) {
+               if (!ifnet_get_address_list(ifns[m], &ifads)) {
                    for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
                        afsi_SetServerIPRank(sa, ifads[j]);
                        cnt++;
@@ -1492,43 +1350,57 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
                    ifnet_free_address_list(ifads);
                }
            }
-           ifnet_list_free(ifn);
+           ifnet_list_free(ifns);
        }
     }
-#elif defined(AFS_DARWIN60_ENV)
+#   elif defined(AFS_DARWIN_ENV)
     {
-       struct ifnet *ifn;
-       struct ifaddr *ifa;
+       rx_ifnet_t ifn;
+       rx_ifaddr_t ifa;
          TAILQ_FOREACH(ifn, &ifnet, if_link) {
            TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
                afsi_SetServerIPRank(sa, ifa);
     }}}
-#elif defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#   elif defined(AFS_FBSD_ENV)
     {
        struct in_ifaddr *ifa;
-         TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
-           afsi_SetServerIPRank(sa, ifa);
-    }}
-#elif defined(AFS_OBSD_ENV)
+       struct rm_priotracker in_ifa_tracker;
+       CURVNET_SET(rx_socket->so_vnet);
+       IN_IFADDR_RLOCK(&in_ifa_tracker);
+       AFS_FBSD_NET_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
+           afsi_SetServerIPRank(sa, &ifa->ia_ifa);
+       }
+       IN_IFADDR_RUNLOCK(&in_ifa_tracker);
+       CURVNET_RESTORE();
+    }
+#   elif defined(AFS_OBSD_ENV)
     {
        extern struct in_ifaddrhead in_ifaddr;
        struct in_ifaddr *ifa;
        for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
            afsi_SetServerIPRank(sa, ifa);
     }
-#else
+#   elif defined(AFS_NBSD40_ENV)
+     {
+       extern struct in_ifaddrhead in_ifaddrhead;
+       struct in_ifaddr *ifa;
+       for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
+           afsi_SetServerIPRank(sa, ifa);
+     }
+#   else
     {
        struct in_ifaddr *ifa;
        for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
            afsi_SetServerIPRank(sa, ifa);
     }}
-#endif
+#   endif
+#  endif                               /* USEIFADDR */
+#  ifndef USEIFADDR
     end:
-#endif                         /* USEIFADDR */
-#endif                         /* AFS_SUN5_ENV */
-#endif                         /* else AFS_USERSPACE_IP_ADDR */
-    if (sa)
-         sa->sa_iprank += afs_randomMod15();
+#  endif
+# endif                                /* AFS_SUN5_ENV */
+#endif                         /* AFS_USERSPACE_IP_ADDR */
+    sa->sa_iprank += afs_randomMod15();
 
     return 0;
 }                              /* afs_SetServerPrefs */
@@ -1542,28 +1414,28 @@ static int afs_SetServerPrefs(struct srvAddr *sa) {
 /* afs_FlushServer()
  * The addresses on this server struct has changed in some way and will
  * clean up all other structures that may reference it.
- * The afs_xserver and afs_xsrvAddr locks are assumed taken.
+ * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
  */
-void afs_FlushServer(struct server *srvp) {
+static void
+afs_FlushServer(struct server *srvp, struct volume *tv)
+{
     afs_int32 i;
     struct server *ts, **pts;
 
     /* Find any volumes residing on this server and flush their state */
-      afs_ResetVolumes(srvp);
+    afs_ResetVolumes(srvp, tv);
 
     /* Flush all callbacks in the all vcaches for this specific server */
-      afs_FlushServerCBs(srvp);
+    afs_FlushServerCBs(srvp);
 
     /* Remove all the callbacks structs */
     if (srvp->cbrs) {
        struct afs_cbr *cb, *cbnext;
 
-         MObtainWriteLock(&afs_xvcb, 300);
        for (cb = srvp->cbrs; cb; cb = cbnext) {
            cbnext = cb->next;
            afs_FreeCBR(cb);
        } srvp->cbrs = (struct afs_cbr *)0;
-       ReleaseWriteLock(&afs_xvcb);
     }
 
     /* If no more srvAddr structs hanging off of this server struct,
@@ -1598,8 +1470,11 @@ void afs_FlushServer(struct server *srvp) {
  * remains connected to a server struct.
  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
  *    It is not removed from the afs_srvAddrs hash chain.
+ * If resetting volumes, do not reset volume tv
  */
-void afs_RemoveSrvAddr(struct srvAddr *sap) {
+static void
+afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
+{
     struct srvAddr **psa, *sa;
     struct server *srv;
 
@@ -1617,23 +1492,123 @@ void afs_RemoveSrvAddr(struct srvAddr *sap) {
        sa->server = 0;
 
        /* Flush the server struct since it's IP address has changed */
-       afs_FlushServer(srv);
+       afs_FlushServer(srv, tv);
+    }
+}
+
+/* afs_GetCapabilities
+ * Try and retrieve capabilities of a given file server. Carps on actual
+ * failure. Servers are not expected to support this RPC. */
+void
+afs_GetCapabilities(struct server *ts)
+{
+    Capabilities caps = {0, NULL};
+    struct vrequest *treq = NULL;
+    struct afs_conn *tc;
+    struct unixuser *tu;
+    struct rx_connection *rxconn;
+    afs_int32 code;
+
+    if ( !ts || !ts->cell )
+       return;
+    if ( !afs_osi_credp )
+       return;
+
+    if ((code = afs_CreateReq(&treq, afs_osi_credp)))
+       return;
+    tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
+    if ( !tu ) {
+       afs_DestroyReq(treq);
+       return;
+    }
+    tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
+                     SHARED_LOCK, 0, &rxconn);
+    afs_PutUser(tu, SHARED_LOCK);
+    if ( !tc ) {
+       afs_DestroyReq(treq);
+       return;
+    }
+    /* InitCallBackStateN, triggered by our RPC, may need this */
+    ReleaseWriteLock(&afs_xserver);
+    AFS_GUNLOCK();
+    code = RXAFS_GetCapabilities(rxconn, &caps);
+    AFS_GLOCK();
+    ObtainWriteLock(&afs_xserver, 723);
+    /* we forced a conn above; important we mark it down if needed */
+    if ((code < 0) && (code != RXGEN_OPCODE)) {
+       afs_ServerDown(tc->parent->srvr, code, rxconn);
+       ForceNewConnections(tc->parent->srvr); /* multi homed clients */
+    }
+    afs_PutConn(tc, rxconn, SHARED_LOCK);
+    if ( code && code != RXGEN_OPCODE ) {
+       afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
+       /* better not be anything to free. we failed! */
+       afs_DestroyReq(treq);
+       return;
+    }
+
+    ts->flags |= SCAPS_KNOWN;
+
+    if ( caps.Capabilities_len > 0 ) {
+       ts->capabilities = caps.Capabilities_val[0];
+       xdr_free((xdrproc_t)xdr_Capabilities, &caps);
+       caps.Capabilities_len = 0;
+       caps.Capabilities_val = NULL;
+    }
+
+    afs_DestroyReq(treq);
+}
+
+static struct server *
+afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
+                struct server **oldts, afs_int32 addr_uniquifier)
+{
+    struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
+    if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
+       /* Found a server struct that is multihomed and same
+        * uniqufier (same IP addrs). The above if statement is the
+        * same as in InstallUVolumeEntry().
+        */
+       return ts;
     }
+    if (ts)
+       *oldts = ts;            /* Will reuse if same uuid */
+    return NULL;
 }
 
-/* afs_GetServer()
- * Return an updated and properly initialized server structure
- * corresponding to the server ID, cell, and port specified.
- * If one does not exist, then one will be created.
- * aserver and aport must be in NET byte order.
+/*!
+ * Return an updated and properly initialized server structure.
+ *
+ * Takes a server ID, cell, and port.
+ * If server does not exist, then one will be created.
+ * @param[in] aserverp
+ *      The server address in network byte order
+ * @param[in] nservers
+ *      The number of IP addresses claimed by the server
+ * @param[in] acell
+ *      The cell the server is in
+ * @param[in] aport
+ *      The port for the server (fileserver or vlserver) in network byte order
+ * @param[in] locktype
+ *      The type of lock to hold when iterating server hash (unused).
+ * @param[in] uuidp
+ *      The uuid for servers supporting one.
+ * @param[in] addr_uniquifier
+ *      The vldb-provider per-instantiated-server uniquifer counter.
+ * @param[in] tv
+ *      A volume not to reset information for if the server addresses
+ *      changed.
+ *
+ * @return
+ *      A server structure matching the request.
  */
-struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
-                            afs_int32 acell, u_short aport,
-                            afs_int32 locktype, afsUUID * uuidp,
-                            afs_int32 addr_uniquifier) {
+struct server *
+afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
+             u_short aport, afs_int32 locktype, afsUUID * uuidp,
+             afs_int32 addr_uniquifier, struct volume *tv)
+{
     struct server *oldts = 0, *ts, *newts, *orphts = 0;
     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
-    u_short fsport;
     afs_int32 iphash, k, srvcount = 0;
     unsigned int srvhash;
 
@@ -1644,7 +1619,7 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
     /* Check if the server struct exists and is up to date */
     if (!uuidp) {
        if (nservers != 1)
-           panic("afs_GetServer: incorect count of servers");
+           panic("afs_GetServer: incorrect count of servers");
        ObtainReadLock(&afs_xsrvAddr);
        ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
        ReleaseReadLock(&afs_xsrvAddr);
@@ -1658,33 +1633,48 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
     } else {
        if (nservers <= 0)
            panic("afs_GetServer: incorrect count of servers");
-       ts = afs_FindServer(0, aport, uuidp, locktype);
-       if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
-           /* Found a server struct that is multihomed and same
-            * uniqufier (same IP addrs). The above if statement is the
-            * same as in InstallUVolumeEntry().
-            */
+
+       ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
+       if (ts) {
            ReleaseSharedLock(&afs_xserver);
            return ts;
        }
-       if (ts)
-           oldts = ts;         /* Will reuse if same uuid */
     }
 
-    UpgradeSToWLock(&afs_xserver, 36);
+    /*
+     * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
+     * Do a little dance and see if we can grab xvcb. If not, we
+     * need to recheck that oldts is still right after a drop and reobtain.
+     */
+    if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
+       ReleaseSharedLock(&afs_xserver);
+       ObtainWriteLock(&afs_xvcb, 299);
+       ObtainWriteLock(&afs_xserver, 35);
+
+       /* we don't know what changed while we didn't hold the lock */
+       oldts = 0;
+       ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
+                             addr_uniquifier);
+       if (ts) {
+           ReleaseWriteLock(&afs_xserver);
+           ReleaseWriteLock(&afs_xvcb);
+           return ts;
+       }
+    } else {
+       UpgradeSToWLock(&afs_xserver, 36);
+    }
     ObtainWriteLock(&afs_xsrvAddr, 116);
-
     srvcount = afs_totalServers;
 
     /* Reuse/allocate a new server structure */
     if (oldts) {
        newts = oldts;
     } else {
-       newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
+       newts = afs_osi_Alloc(sizeof(struct server));
        if (!newts)
            panic("malloc of server struct");
        afs_totalServers++;
-       memset((char *)newts, 0, sizeof(struct server));
+       memset(newts, 0, sizeof(struct server));
 
        /* Add the server struct to the afs_servers[] hash chain */
        srvhash =
@@ -1700,9 +1690,8 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
        newts->flags |= SRVR_MULTIHOMED;
     }
     if (acell)
-       newts->cell = afs_GetCell(acell, 0);
-
-    fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
+       /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
+       newts->cell = afs_GetCellStale(acell, 0);
 
     /* For each IP address we are registering */
     for (k = 0; k < nservers; k++) {
@@ -1716,7 +1705,7 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
                break;
        }
        if (oldsa && (oldsa->server != newts)) {
-           afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
+           afs_RemoveSrvAddr(oldsa, tv);       /* Remove from its server struct */
            oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
            newts->addr = oldsa;
        }
@@ -1725,11 +1714,11 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
        if (oldsa) {
            newsa = oldsa;
        } else {
-           newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
+           newsa = afs_osi_Alloc(sizeof(struct srvAddr));
            if (!newsa)
                panic("malloc of srvAddr struct");
            afs_totalSrvAddrs++;
-           memset((char *)newsa, 0, sizeof(struct srvAddr));
+           memset(newsa, 0, sizeof(struct srvAddr));
 
            /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
            newsa->next_bkt = afs_srvAddrs[iphash];
@@ -1775,16 +1764,15 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
 
            /* Have a srvAddr struct. Now get a server struct (if not already) */
            if (!orphts) {
-               orphts =
-                   (struct server *)afs_osi_Alloc(sizeof(struct server));
+               orphts = afs_osi_Alloc(sizeof(struct server));
                if (!orphts)
                    panic("malloc of lo server struct");
-               memset((char *)orphts, 0, sizeof(struct server));
+               memset(orphts, 0, sizeof(struct server));
                afs_totalServers++;
 
                /* Add the orphaned server to the afs_servers[] hash chain.
                 * Its iphash does not matter since we never look up the server
-                * in the afs_servers table by its ip address (only by uuid - 
+                * in the afs_servers table by its ip address (only by uuid -
                 * which this has none).
                 */
                iphash = SHash(aserverp[k]);
@@ -1792,13 +1780,14 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
                afs_servers[iphash] = orphts;
 
                if (acell)
-                   orphts->cell = afs_GetCell(acell, 0);
+                   /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
+                   orphts->cell = afs_GetCellStale(acell, 0);
            }
 
            /* Hang the srvAddr struct off of the server structure. The server
             * may have multiple srvAddrs, but it won't be marked multihomed.
             */
-           afs_RemoveSrvAddr(orphsa);  /* remove */
+           afs_RemoveSrvAddr(orphsa, tv);      /* remove */
            orphsa->next_sa = orphts->addr;     /* hang off server struct */
            orphts->addr = orphsa;
            orphsa->server = orphts;
@@ -1806,6 +1795,8 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
            orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
        }
     }
+    /* We can't need this below, and won't reacquire */
+    ReleaseWriteLock(&afs_xvcb);
 
     srvcount = afs_totalServers - srvcount;    /* # servers added and removed */
     if (srvcount) {
@@ -1821,13 +1812,19 @@ struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
     }
 
     ReleaseWriteLock(&afs_xsrvAddr);
+
+    if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
+       afs_GetCapabilities(newts);
+
     ReleaseWriteLock(&afs_xserver);
     return (newts);
 }                              /* afs_GetServer */
 
-void afs_ActivateServer(struct srvAddr *sap) {
-    osi_timeval_t currTime;    /*Filled with current time */
-    osi_timeval_t *currTimeP;  /*Ptr to above */
+void
+afs_ActivateServer(struct srvAddr *sap)
+{
+    osi_timeval32_t currTime;  /*Filled with current time */
+    osi_timeval32_t *currTimeP;        /*Ptr to above */
     struct afs_stats_SrvUpDownInfo *upDownP;   /*Ptr to up/down info record */
     struct server *aserver = sap->server;
 
@@ -1838,7 +1835,7 @@ void afs_ActivateServer(struct srvAddr *sap) {
         */
        aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
        currTimeP = &currTime;
-       osi_GetuTime(currTimeP);
+       osi_GetTime(currTimeP);
        aserver->activationTime = currTime.tv_sec;
        upDownP = GetUpDownStats(aserver);
        if (aserver->flags & SRVR_ISDOWN) {
@@ -1850,32 +1847,25 @@ void afs_ActivateServer(struct srvAddr *sap) {
     }
 }
 
-void afs_RemoveAllConns()
+void
+afs_RemoveAllConns(void)
 {
     int i;
     struct server *ts, *nts;
     struct srvAddr *sa;
-    struct afs_conn *tc, *ntc;
 
     ObtainReadLock(&afs_xserver);
     ObtainWriteLock(&afs_xconn, 1001);
-    
+
     /*printf("Destroying connections ... ");*/
     for (i = 0; i < NSERVERS; i++) {
         for (ts = afs_servers[i]; ts; ts = nts) {
             nts = ts->next;
             for (sa = ts->addr; sa; sa = sa->next_sa) {
                 if (sa->conns) {
-                    tc = sa->conns;
-                    while (tc) {
-                        ntc = tc->next;
-                        AFS_GUNLOCK();
-                        rx_DestroyConnection(tc->id);
-                        AFS_GLOCK();
-                        afs_osi_Free(tc, sizeof(struct afs_conn));
-                        tc = ntc;
-                    }
+                    afs_ReleaseConns(sa->conns);
                     sa->conns = NULL;
+                   sa->natping = NULL;
                 }
             }
         }
@@ -1884,10 +1874,11 @@ void afs_RemoveAllConns()
 
     ReleaseWriteLock(&afs_xconn);
     ReleaseReadLock(&afs_xserver);
-    
+
 }
 
-void afs_MarkAllServersUp()
+void
+afs_MarkAllServersUp(void)
 {
     int i;
     struct server *ts;
@@ -1905,30 +1896,3 @@ void afs_MarkAllServersUp()
     ReleaseWriteLock(&afs_xsrvAddr);
     ReleaseWriteLock(&afs_xserver);
 }
-
-void shutdown_server()
-{
-    int i;
-
-    for (i = 0; i < NSERVERS; i++) {
-       struct server *ts, *next;
-
-        ts = afs_servers[i];
-        while(ts) {
-           next = ts->next;
-           afs_osi_Free(ts, sizeof(struct server));
-           ts = next;
-        }
-    }
-
-    for (i = 0; i < NSERVERS; i++) {
-       struct srvAddr *sa, *next;
-
-        sa = afs_srvAddrs[i];
-        while(sa) {
-           next = sa->next_bkt;
-           afs_osi_Free(sa, sizeof(struct srvAddr));
-           sa = next;
-        }
-    }
-}