libafs: add replicated connection pool
[openafs.git] / src / afs / afs_server.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Implements:
12  * afs_MarkServerUpOrDown
13  * afs_ServerDown
14  * afs_CountServers
15  * afs_CheckServers
16  * afs_FindServer
17  * afs_random
18  * afs_randomMod127
19  * afs_SortServers
20  * afsi_SetServerIPRank
21  * afs_GetServer
22  * afs_ActivateServer
23  *
24  *
25  * Local:
26  * HaveCallBacksFrom
27  * CheckVLServer
28  * afs_SortOneServer
29  * afs_SetServerPrefs
30  *
31  */
32 #include <afsconfig.h>
33 #include "afs/param.h"
34
35
36 #include "afs/stds.h"
37 #include "afs/sysincludes.h"    /* Standard vendor system headers */
38
39 #if !defined(UKERNEL)
40 #if !defined(AFS_LINUX20_ENV)
41 #include <net/if.h>
42 #endif
43 #include <netinet/in.h>
44
45 #ifdef AFS_SGI62_ENV
46 #include "h/hashing.h"
47 #endif
48 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
49 #include <netinet/in_var.h>
50 #endif /* AFS_HPUX110_ENV */
51 #ifdef AFS_DARWIN_ENV
52 #include <net/if_var.h>
53 #endif
54 #endif /* !defined(UKERNEL) */
55
56 #include "afsincludes.h"        /* Afs-based standard headers */
57 #include "afs/afs_stats.h"      /* afs statistics */
58 #include "rx/rx_multi.h"
59
60 #if     defined(AFS_SUN5_ENV)
61 #include <inet/led.h>
62 #include <inet/common.h>
63 #include <netinet/ip6.h>
64 #define ipif_local_addr ipif_lcl_addr
65 #ifndef V4_PART_OF_V6
66 # define V4_PART_OF_V6(v6)       v6.s6_addr32[3]
67 #endif
68 #include <inet/ip.h>
69 #endif
70
71 /* Exported variables */
72 afs_rwlock_t afs_xserver;       /* allocation lock for servers */
73 struct server *afs_servers[NSERVERS];   /* Hashed by server`s uuid & 1st ip */
74 afs_rwlock_t afs_xsrvAddr;      /* allocation lock for srvAddrs */
75 struct srvAddr *afs_srvAddrs[NSERVERS]; /* Hashed by server's ip */
76
77
78 /* debugging aids - number of alloc'd server and srvAddr structs. */
79 int afs_reuseServers = 0;
80 int afs_reuseSrvAddrs = 0;
81 int afs_totalServers = 0;
82 int afs_totalSrvAddrs = 0;
83
84
85
86 static struct afs_stats_SrvUpDownInfo *
87 GetUpDownStats(struct server *srv)
88 {
89     struct afs_stats_SrvUpDownInfo *upDownP;
90     u_short fsport = AFS_FSPORT;
91
92     if (srv->cell)
93         fsport = srv->cell->fsport;
94
95     if (srv->addr->sa_portal == fsport)
96         upDownP = afs_stats_cmperf.fs_UpDown;
97     else
98         upDownP = afs_stats_cmperf.vl_UpDown;
99
100     if (srv->cell && afs_IsPrimaryCell(srv->cell))
101         return &upDownP[AFS_STATS_UPDOWN_IDX_SAME_CELL];
102     else
103         return &upDownP[AFS_STATS_UPDOWN_IDX_DIFF_CELL];
104 }
105
106
107 /*------------------------------------------------------------------------
108  * afs_MarkServerUpOrDown
109  *
110  * Description:
111  *      Mark the given server up or down, and track its uptime stats.
112  *
113  * Arguments:
114  *      a_serverP : Ptr to server record to fiddle with.
115  *      a_isDown  : Is the server is to be marked down?
116  *
117  * Returns:
118  *      Nothing.
119  *
120  * Environment:
121  *      The CM server structures must be write-locked.
122  *
123  * Side Effects:
124  *      As advertised.
125  *------------------------------------------------------------------------*/
126
127 void
128 afs_MarkServerUpOrDown(struct srvAddr *sa, int a_isDown)
129 {
130     struct server *a_serverP = sa->server;
131     struct srvAddr *sap;
132     osi_timeval_t currTime, *currTimeP; /*Current time */
133     afs_int32 downTime;         /*Computed downtime, in seconds */
134     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
135
136     /*
137      * If the server record is marked the same as the new status we've
138      * been fed, then there isn't much to be done.
139      */
140     if ((a_isDown && (sa->sa_flags & SRVADDR_ISDOWN))
141         || (!a_isDown && !(sa->sa_flags & SRVADDR_ISDOWN)))
142         return;
143
144     if (a_isDown) {
145         sa->sa_flags |= SRVADDR_ISDOWN;
146         for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
147             if (!(sap->sa_flags & SRVADDR_ISDOWN)) {
148                 /* Not all ips are up so don't bother with the
149                  * server's up/down stats */
150                 return;
151             }
152         }
153         /*
154          * All ips are down we treat the whole server down
155          */
156         a_serverP->flags |= SRVR_ISDOWN;
157     } else {
158         sa->sa_flags &= ~SRVADDR_ISDOWN;
159         /* If any ips are up, the server is also marked up */
160         a_serverP->flags &= ~SRVR_ISDOWN;
161         for (sap = a_serverP->addr; sap; sap = sap->next_sa) {
162             if (sap->sa_flags & SRVADDR_ISDOWN) {
163                 /* Not all ips are up so don't bother with the
164                  * server's up/down stats */
165                 return;
166             }
167         }
168     }
169 #ifndef AFS_NOSTATS
170     /*
171      * Compute the current time and which overall stats record is to be
172      * updated; we'll need them one way or another.
173      */
174     currTimeP = &currTime;
175     osi_GetuTime(currTimeP);
176
177     upDownP = GetUpDownStats(a_serverP);
178
179     if (a_isDown) {
180         /*
181          * Server going up -> down; remember the beginning of this
182          * downtime incident.
183          */
184         a_serverP->lastDowntimeStart = currTime.tv_sec;
185
186         (upDownP->numDownRecords)++;
187         (upDownP->numUpRecords)--;
188     } /*Server being marked down */
189     else {
190         /*
191          * Server going down -> up; remember everything about this
192          * newly-completed downtime incident.
193          */
194         downTime = currTime.tv_sec - a_serverP->lastDowntimeStart;
195         (a_serverP->numDowntimeIncidents)++;
196         a_serverP->sumOfDowntimes += downTime;
197
198         (upDownP->numUpRecords)++;
199         (upDownP->numDownRecords)--;
200         (upDownP->numDowntimeIncidents)++;
201         if (a_serverP->numDowntimeIncidents == 1)
202             (upDownP->numRecordsNeverDown)--;
203         upDownP->sumOfDowntimes += downTime;
204         if ((upDownP->shortestDowntime == 0)
205             || (downTime < upDownP->shortestDowntime))
206             upDownP->shortestDowntime = downTime;
207         if ((upDownP->longestDowntime == 0)
208             || (downTime > upDownP->longestDowntime))
209             upDownP->longestDowntime = downTime;
210
211
212         if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET0)
213             (upDownP->downDurations[0])++;
214         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET1)
215             (upDownP->downDurations[1])++;
216         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET2)
217             (upDownP->downDurations[2])++;
218         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET3)
219             (upDownP->downDurations[3])++;
220         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET4)
221             (upDownP->downDurations[4])++;
222         else if (downTime <= AFS_STATS_MAX_DOWNTIME_DURATION_BUCKET5)
223             (upDownP->downDurations[5])++;
224         else
225             (upDownP->downDurations[6])++;
226
227     }                           /*Server being marked up */
228 #endif
229 }                               /*MarkServerUpOrDown */
230
231
232 afs_int32
233 afs_ServerDown(struct srvAddr *sa, int code)
234 {
235     struct server *aserver = sa->server;
236
237     AFS_STATCNT(ServerDown);
238     if (aserver->flags & SRVR_ISDOWN || sa->sa_flags & SRVADDR_ISDOWN)
239         return 0;
240     afs_MarkServerUpOrDown(sa, SRVR_ISDOWN);
241     if (sa->sa_portal == aserver->cell->vlport)
242         print_internet_address
243             ("afs: Lost contact with volume location server ", sa, "", 1, code);
244     else
245         print_internet_address("afs: Lost contact with file server ", sa, "",
246                                1, code);
247     return 1;
248 }                               /*ServerDown */
249
250
251 /* return true if we have any callback promises from this server */
252 int
253 afs_HaveCallBacksFrom(struct server *aserver)
254 {
255     afs_int32 now;
256     int i;
257     struct vcache *tvc;
258
259     AFS_STATCNT(HaveCallBacksFrom);
260     now = osi_Time();           /* for checking for expired callbacks */
261     for (i = 0; i < VCSIZE; i++) {      /* for all guys in the hash table */
262         for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
263             /*
264              * Check to see if this entry has an unexpired callback promise
265              * from the required host
266              */
267             if (aserver == tvc->callback && tvc->cbExpires >= now
268                 && ((tvc->f.states & CRO) == 0))
269                 return 1;
270         }
271     }
272     return 0;
273
274 }                               /*HaveCallBacksFrom */
275
276
277 static void
278 CheckVLServer(struct srvAddr *sa, struct vrequest *areq)
279 {
280     struct server *aserver = sa->server;
281     struct afs_conn *tc;
282     afs_int32 code;
283     struct rx_connection *rxconn;
284
285     AFS_STATCNT(CheckVLServer);
286     /* Ping dead servers to see if they're back */
287     if (!((aserver->flags & SRVR_ISDOWN) || (sa->sa_flags & SRVADDR_ISDOWN))
288         || (aserver->flags & SRVR_ISGONE))
289         return;
290     if (!aserver->cell)
291         return;                 /* can't do much */
292
293     tc = afs_ConnByHost(aserver, aserver->cell->vlport,
294                         aserver->cell->cellNum, areq, 1, SHARED_LOCK, 0,
295                         &rxconn);
296     if (!tc)
297         return;
298     rx_SetConnDeadTime(rxconn, 3);
299
300     RX_AFS_GUNLOCK();
301     code = VL_ProbeServer(rxconn);
302     RX_AFS_GLOCK();
303     rx_SetConnDeadTime(rxconn, afs_rx_deadtime);
304     afs_PutConn(tc, rxconn, SHARED_LOCK);
305     /*
306      * If probe worked, or probe call not yet defined (for compatibility
307      * with old vlsevers), then we treat this server as running again
308      */
309     if (code == 0 || (code <= -450 && code >= -470)) {
310         if (tc->parent->srvr == sa) {
311             afs_MarkServerUpOrDown(sa, 0);
312             print_internet_address("afs: volume location server ", sa,
313                                    " is back up", 2, code);
314         }
315     }
316
317 }                               /*CheckVLServer */
318
319
320 #ifndef AFS_MINCHANGE           /* So that some can increase it in param.h */
321 #define AFS_MINCHANGE 2         /* min change we'll bother with */
322 #endif
323 #ifndef AFS_MAXCHANGEBACK
324 #define AFS_MAXCHANGEBACK 10    /* max seconds we'll set a clock back at once */
325 #endif
326
327
328 /*------------------------------------------------------------------------
329  * EXPORTED afs_CountServers
330  *
331  * Description:
332  *      Originally meant to count the number of servers and determining
333  *      up/down info, this routine will now simply sum up all of the
334  *      server record ages.  All other up/down information is kept on the
335  *      fly.
336  *
337  * Arguments:
338  *      None.
339  *
340  * Returns:
341  *      Nothing.
342  *
343  * Environment:
344  *      This routine locks afs_xserver for write for the duration.
345  *
346  * Side Effects:
347  *      Set CM perf stats field sumOfRecordAges for all server record
348  *      entries.
349  *------------------------------------------------------------------------*/
350
351 void
352 afs_CountServers(void)
353 {
354     int currIdx;                /*Curr idx into srv table */
355     struct server *currSrvP;    /*Ptr to curr server record */
356     afs_int32 currChainLen;     /*Length of curr hash chain */
357     osi_timeval_t currTime;     /*Current time */
358     osi_timeval_t *currTimeP;   /*Ptr to above */
359     afs_int32 srvRecordAge;     /*Age of server record, in secs */
360     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to current up/down
361                                                  * info being manipulated */
362
363     /*
364      * Write-lock the server table so we don't get any interference.
365      */
366     ObtainReadLock(&afs_xserver);
367
368     /*
369      * Iterate over each hash index in the server table, walking down each
370      * chain and tallying what we haven't computed from the records there on
371      * the fly.  First, though, initialize the tallies that will change.
372      */
373     afs_stats_cmperf.srvMaxChainLength = 0;
374
375     afs_stats_cmperf.fs_UpDown[0].sumOfRecordAges = 0;
376     afs_stats_cmperf.fs_UpDown[0].ageOfYoungestRecord = 0;
377     afs_stats_cmperf.fs_UpDown[0].ageOfOldestRecord = 0;
378     memset(afs_stats_cmperf.fs_UpDown[0].downIncidents, 0,
379            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
380
381     afs_stats_cmperf.fs_UpDown[1].sumOfRecordAges = 0;
382     afs_stats_cmperf.fs_UpDown[1].ageOfYoungestRecord = 0;
383     afs_stats_cmperf.fs_UpDown[1].ageOfOldestRecord = 0;
384     memset(afs_stats_cmperf.fs_UpDown[1].downIncidents, 0,
385            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
386
387     afs_stats_cmperf.vl_UpDown[0].sumOfRecordAges = 0;
388     afs_stats_cmperf.vl_UpDown[0].ageOfYoungestRecord = 0;
389     afs_stats_cmperf.vl_UpDown[0].ageOfOldestRecord = 0;
390     memset(afs_stats_cmperf.vl_UpDown[0].downIncidents, 0,
391            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
392
393     afs_stats_cmperf.vl_UpDown[1].sumOfRecordAges = 0;
394     afs_stats_cmperf.vl_UpDown[1].ageOfYoungestRecord = 0;
395     afs_stats_cmperf.vl_UpDown[1].ageOfOldestRecord = 0;
396     memset(afs_stats_cmperf.vl_UpDown[1].downIncidents, 0,
397            AFS_STATS_NUM_DOWNTIME_INCIDENTS_BUCKETS * sizeof(afs_int32));
398
399     /*
400      * Compute the current time, used to figure out server record ages.
401      */
402     currTimeP = &currTime;
403     osi_GetuTime(currTimeP);
404
405     /*
406      * Sweep the server hash table, tallying all we need to know.
407      */
408     for (currIdx = 0; currIdx < NSERVERS; currIdx++) {
409         currChainLen = 0;
410         for (currSrvP = afs_servers[currIdx]; currSrvP;
411              currSrvP = currSrvP->next) {
412             /*
413              * Bump the current chain length.
414              */
415             currChainLen++;
416
417             /*
418              * Any further tallying for this record will only be done if it has
419              * been activated.
420              */
421             if ((currSrvP->flags & AFS_SERVER_FLAG_ACTIVATED)
422                 && currSrvP->addr && currSrvP->cell) {
423
424                 /*
425                  * Compute the current server record's age, then remember it
426                  * in the appropriate places.
427                  */
428                 srvRecordAge = currTime.tv_sec - currSrvP->activationTime;
429                 upDownP = GetUpDownStats(currSrvP);
430                 upDownP->sumOfRecordAges += srvRecordAge;
431                 if ((upDownP->ageOfYoungestRecord == 0)
432                     || (srvRecordAge < upDownP->ageOfYoungestRecord))
433                     upDownP->ageOfYoungestRecord = srvRecordAge;
434                 if ((upDownP->ageOfOldestRecord == 0)
435                     || (srvRecordAge > upDownP->ageOfOldestRecord))
436                     upDownP->ageOfOldestRecord = srvRecordAge;
437
438                 if (currSrvP->numDowntimeIncidents <=
439                     AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET0)
440                     (upDownP->downIncidents[0])++;
441                 else if (currSrvP->numDowntimeIncidents <=
442                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET1)
443                     (upDownP->downIncidents[1])++;
444                 else if (currSrvP->numDowntimeIncidents <=
445                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET2)
446                     (upDownP->downIncidents[2])++;
447                 else if (currSrvP->numDowntimeIncidents <=
448                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET3)
449                     (upDownP->downIncidents[3])++;
450                 else if (currSrvP->numDowntimeIncidents <=
451                          AFS_STATS_MAX_DOWNTIME_INCIDENTS_BUCKET4)
452                     (upDownP->downIncidents[4])++;
453                 else
454                     (upDownP->downIncidents[5])++;
455
456
457             }                   /*Current server has been active */
458         }                       /*Walk this chain */
459
460         /*
461          * Before advancing to the next chain, remember facts about this one.
462          */
463         if (currChainLen > afs_stats_cmperf.srvMaxChainLength) {
464             /*
465              * We beat out the former champion (which was initially set to 0
466              * here).  Mark down the new winner, and also remember if it's an
467              * all-time winner.
468              */
469             afs_stats_cmperf.srvMaxChainLength = currChainLen;
470             if (currChainLen > afs_stats_cmperf.srvMaxChainLengthHWM)
471                 afs_stats_cmperf.srvMaxChainLengthHWM = currChainLen;
472         }                       /*Update chain length maximum */
473     }                           /*For each hash chain */
474
475     /*
476      * We're done.  Unlock the server table before returning to our caller.
477      */
478     ReleaseReadLock(&afs_xserver);
479
480 }                               /*afs_CountServers */
481
482
483 void
484 ForceAllNewConnections(void)
485 {
486     int srvAddrCount;
487     struct srvAddr **addrs;
488     struct srvAddr *sa;
489     afs_int32 i, j;
490
491     ObtainReadLock(&afs_xserver);       /* Necessary? */
492     ObtainReadLock(&afs_xsrvAddr);
493
494     srvAddrCount = 0;
495     for (i = 0; i < NSERVERS; i++) {
496         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
497             srvAddrCount++;
498         }
499     }
500
501     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
502     osi_Assert(addrs != NULL);
503     j = 0;
504     for (i = 0; i < NSERVERS; i++) {
505         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
506             if (j >= srvAddrCount)
507                 break;
508             addrs[j++] = sa;
509         }
510     }
511
512     ReleaseReadLock(&afs_xsrvAddr);
513     ReleaseReadLock(&afs_xserver);
514     for (i = 0; i < j; i++) {
515         sa = addrs[i];
516         ForceNewConnections(sa);
517     }
518 }
519
520 static void
521 CkSrv_MarkUpDown(struct afs_conn **conns, int nconns, afs_int32 *results)
522 {
523     struct srvAddr *sa;
524     struct afs_conn *tc;
525     afs_int32 i;
526
527     for(i = 0; i < nconns; i++){
528         tc = conns[i];
529         sa = tc->parent->srvr;
530
531         if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
532             (tc->parent->srvr == sa)) {
533             /* server back up */
534             print_internet_address("afs: file server ", sa, " is back up", 2,
535                                    results[i]);
536
537             ObtainWriteLock(&afs_xserver, 244);
538             ObtainWriteLock(&afs_xsrvAddr, 245);
539             afs_MarkServerUpOrDown(sa, 0);
540             ReleaseWriteLock(&afs_xsrvAddr);
541             ReleaseWriteLock(&afs_xserver);
542
543             if (afs_waitForeverCount) {
544                 afs_osi_Wakeup(&afs_waitForever);
545             }
546         } else {
547             if (results[i] < 0) {
548                 /* server crashed */
549                 afs_ServerDown(sa, results[i]);
550                 ForceNewConnections(sa);  /* multi homed clients */
551             }
552         }
553     }
554 }
555
556 void
557 CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
558               struct afs_conn **conns)
559 {
560     Capabilities *caps;
561     afs_int32 *results;
562     afs_int32 i;
563     struct server *ts;
564
565     caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
566     osi_Assert(caps != NULL);
567     memset(caps, 0, nconns * sizeof(Capabilities));
568
569     results = afs_osi_Alloc(nconns * sizeof (afs_int32));
570     osi_Assert(results != NULL);
571
572     AFS_GUNLOCK();
573     multi_Rx(rxconns,nconns)
574       {
575         multi_RXAFS_GetCapabilities(&caps[multi_i]);
576         results[multi_i] = multi_error;
577       } multi_End;
578     AFS_GLOCK();
579
580     for ( i = 0 ; i < nconns ; i++ ) {
581         ts = conns[i]->parent->srvr->server;
582         if ( !ts )
583             continue;
584         ts->capabilities = 0;
585         ts->flags |= SCAPS_KNOWN;
586         if ( results[i] == RXGEN_OPCODE ) {
587             /* Mark server as up - it responded */
588             results[i] = 0;
589             continue;
590         }
591         if ( results[i] >= 0 )
592             /* we currently handle 32-bits of capabilities */
593             if (caps[i].Capabilities_len > 0) {
594                 ts->capabilities = caps[i].Capabilities_val[0];
595                 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
596                 caps[i].Capabilities_val = NULL;
597                 caps[i].Capabilities_len = 0;
598             }
599     }
600     CkSrv_MarkUpDown(conns, nconns, results);
601
602     afs_osi_Free(caps, nconns * sizeof(Capabilities));
603     afs_osi_Free(results, nconns * sizeof(afs_int32));
604 }
605
606 /* check down servers (if adown), or running servers (if !adown) */
607 void
608 afs_CheckServers(int adown, struct cell *acellp)
609 {
610     afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
611 }
612
613 /* adown: AFS_LS_UP   - check only up
614  *        AFS_LS_DOWN - check only down.
615  *        AFS_LS_ALL  - check all */
616 void
617 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
618                 void (*func1) (int nservers, struct rx_connection **rxconns,
619                                struct afs_conn **conns),
620                 void (*func2) (int nservers, struct rx_connection **rxconns,
621                                struct afs_conn **conns))
622 {
623     struct vrequest treq;
624     struct server *ts;
625     struct srvAddr *sa;
626     struct afs_conn *tc = NULL;
627     afs_int32 i, j;
628     afs_int32 code;
629     struct unixuser *tu;
630     int srvAddrCount;
631     struct srvAddr **addrs;
632     struct afs_conn **conns;
633     int nconns;
634     struct rx_connection **rxconns;
635     afs_int32 *conntimer;
636
637     AFS_STATCNT(afs_CheckServers);
638
639     /*
640      * No sense in doing the server checks if we are running in disconnected
641      * mode
642      */
643     if (AFS_IS_DISCONNECTED)
644         return;
645
646     conns = (struct afs_conn **)0;
647     rxconns = (struct rx_connection **) 0;
648     conntimer = 0;
649     nconns = 0;
650
651     if ((code = afs_InitReq(&treq, afs_osi_credp)))
652         return;
653     ObtainReadLock(&afs_xserver);       /* Necessary? */
654     ObtainReadLock(&afs_xsrvAddr);
655
656     srvAddrCount = 0;
657     for (i = 0; i < NSERVERS; i++) {
658         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
659             srvAddrCount++;
660         }
661     }
662
663     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
664     osi_Assert(addrs != NULL);
665     j = 0;
666     for (i = 0; i < NSERVERS; i++) {
667         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
668             if (j >= srvAddrCount)
669                 break;
670             addrs[j++] = sa;
671         }
672     }
673
674     ReleaseReadLock(&afs_xsrvAddr);
675     ReleaseReadLock(&afs_xserver);
676
677     conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
678     osi_Assert(conns != NULL);
679     rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
680     osi_Assert(rxconns != NULL);
681     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
682     osi_Assert(conntimer != NULL);
683
684     for (i = 0; i < j; i++) {
685         struct rx_connection *rxconn;
686         sa = addrs[i];
687         ts = sa->server;
688         if (!ts)
689             continue;
690
691         /* See if a cell to check was specified.  If it is spec'd and not
692          * this server's cell, just skip the server.
693          */
694         if (acellp && acellp != ts->cell)
695             continue;
696
697         if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
698             || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
699             continue;
700
701         /* check vlserver with special code */
702         if (sa->sa_portal == AFS_VLPORT) {
703             if (vlalso)
704                 CheckVLServer(sa, &treq);
705             continue;
706         }
707
708         if (!ts->cell)          /* not really an active server, anyway, it must */
709             continue;           /* have just been added by setsprefs */
710
711         /* get a connection, even if host is down; bumps conn ref count */
712         tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
713         tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
714                           1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
715                           &rxconn);
716         afs_PutUser(tu, SHARED_LOCK);
717         if (!tc)
718             continue;
719
720         if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
721             conns[nconns]=tc;
722             rxconns[nconns]=rxconn;
723             if (sa->sa_flags & SRVADDR_ISDOWN) {
724                 rx_SetConnDeadTime(rxconn, 3);
725                 conntimer[nconns]=1;
726             } else {
727                 conntimer[nconns]=0;
728             }
729             nconns++;
730         } else /* not holding, kill ref */
731             afs_PutConn(tc, rxconn, SHARED_LOCK);
732     } /* Outer loop over addrs */
733
734     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
735     addrs = NULL;
736
737     (*func1)(nconns, rxconns, conns);
738
739     if (func2) {
740         (*func2)(nconns, rxconns, conns);
741     }
742
743     for (i = 0; i < nconns; i++) {
744         if (conntimer[i] == 1)
745             rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
746         afs_PutConn(conns[i], rxconns[i], SHARED_LOCK);     /* done with it now */
747     }
748
749     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
750     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
751     afs_osi_Free(conntimer, j * sizeof(afs_int32));
752
753 } /*afs_CheckServers*/
754
755
756 /* find a server structure given the host address */
757 struct server *
758 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
759                afs_int32 locktype)
760 {
761     struct server *ts;
762     struct srvAddr *sa;
763     int i;
764
765     AFS_STATCNT(afs_FindServer);
766     if (uuidp) {
767         i = afs_uuid_hash(uuidp) % NSERVERS;
768         for (ts = afs_servers[i]; ts; ts = ts->next) {
769             if ((ts->flags & SRVR_MULTIHOMED)
770                 &&
771                 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
772                  == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
773                 return ts;
774         }
775     } else {
776         i = SHash(aserver);
777         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
778             if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
779                 return sa->server;
780             }
781         }
782     }
783     return NULL;
784
785 }                               /*afs_FindServer */
786
787
788 /* some code for creating new server structs and setting preferences follows
789  * in the next few lines...
790  */
791
792 #define MAXDEFRANK 60000
793 #define DEFRANK    40000
794
795 /* Random number generator and constants from KnuthV2 2d ed, p170 */
796
797 /* Rules:
798    X = (aX + c) % m
799    m is a power of two
800    a % 8 is 5
801    a is 0.73m  should be 0.01m .. 0.99m
802    c is more or less immaterial.  1 or a is suggested.
803
804 NB:  LOW ORDER BITS are not very random.  To get small random numbers,
805      treat result as <1, with implied binary point, and multiply by
806      desired modulus.
807 NB:  Has to be unsigned, since shifts on signed quantities may preserve
808      the sign bit.
809 */
810 /* added rxi_getaddr() to try to get as much initial randomness as
811    possible, since at least one customer reboots ALL their clients
812    simultaneously -- so osi_Time is bound to be the same on some of the
813    clients.  This is probably OK, but I don't want to see too much of it.
814 */
815
816 #define ranstage(x)     (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
817
818 unsigned int
819 afs_random(void)
820 {
821     static afs_int32 state = 0;
822     int i;
823
824     AFS_STATCNT(afs_random);
825     if (!state) {
826         osi_timeval_t t;
827         osi_GetTime(&t);
828         /*
829          * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
830          * bits are in a tv_usec
831          */
832         state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
833         state += (t.tv_sec & 0xff);
834         for (i = 0; i < 30; i++) {
835             ranstage(state);
836         }
837     }
838
839     ranstage(state);
840     return (state);
841
842 }                               /*afs_random */
843
844 /* returns int 0..14 using the high bits of a pseudo-random number instead of
845    the low bits, as the low bits are "less random" than the high ones...
846    slight roundoff error exists, an excercise for the reader.
847    need to multiply by something with lots of ones in it, so multiply by
848    8 or 16 is right out.
849  */
850 int
851 afs_randomMod15(void)
852 {
853     afs_uint32 temp;
854
855     temp = afs_random() >> 4;
856     temp = (temp * 15) >> 28;
857
858     return temp;
859 }
860
861 int
862 afs_randomMod127(void)
863 {
864     afs_uint32 temp;
865
866     temp = afs_random() >> 7;
867     temp = (temp * 127) >> 25;
868
869     return temp;
870 }
871
872 /* afs_SortOneServer()
873  * Sort all of the srvAddrs, of a server struct, by rank from low to high.
874  */
875 void
876 afs_SortOneServer(struct server *asp)
877 {
878     struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
879     int lowrank, rank;
880
881     for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
882         lowprev = NULL;
883         lowsa = *rootsa;        /* lowest sa is the first one */
884         lowrank = lowsa->sa_iprank;
885
886         for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
887             rank = tsa->next_sa->sa_iprank;
888             if (rank < lowrank) {
889                 lowprev = tsa;
890                 lowsa = tsa->next_sa;
891                 lowrank = lowsa->sa_iprank;
892             }
893         }
894         if (lowprev) {          /* found one lower, so rearrange them */
895             lowprev->next_sa = lowsa->next_sa;
896             lowsa->next_sa = *rootsa;
897             *rootsa = lowsa;
898         }
899     }
900 }
901
902 /* afs_SortServer()
903  * Sort the pointer to servers by the server's rank (its lowest rank).
904  * It is assumed that the server already has its IP addrs sorted (the
905  * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
906  */
907 void
908 afs_SortServers(struct server *aservers[], int count)
909 {
910     struct server *ts;
911     int i, j, low;
912
913     AFS_STATCNT(afs_SortServers);
914
915     for (i = 0; i < count; i++) {
916         if (!aservers[i])
917             break;
918         for (low = i, j = i + 1; j <= count; j++) {
919             if ((!aservers[j]) || (!aservers[j]->addr))
920                 break;
921             if ((!aservers[low]) || (!aservers[low]->addr))
922                 break;
923             if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
924                 low = j;
925             }
926         }
927         if (low != i) {
928             ts = aservers[i];
929             aservers[i] = aservers[low];
930             aservers[low] = ts;
931         }
932     }
933 }                               /*afs_SortServers */
934
935 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
936    data structures to determine what the local IP addresses and subnet masks
937    are in order to choose which server(s) are on the local subnet.
938
939    As I see it, there are several cases:
940    1. The server address is one of this host's local addresses.  In this case
941           this server is to be preferred over all others.
942    2. The server is on the same subnet as one of the this host's local
943       addresses.  (ie, an odd-sized subnet, not class A,B,orC)
944    3. The server is on the same net as this host (class A,B or C)
945    4. The server is on a different logical subnet or net than this host, but
946    this host is a 'metric 0 gateway' to it.  Ie, two address-spaces share
947    one physical medium.
948    5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
949    server.
950    6. This host and the server are disjoint.
951
952    That is a rough order of preference.  If a point-to-point link has a high
953    metric, I'm assuming that it is a very slow link, and putting it at the
954    bottom of the list (at least until RX works better over slow links).  If
955    its metric is 1, I'm assuming that it's relatively fast (T1) and putting
956    it ahead of #6.
957    It's not easy to check for case #4, so I'm ignoring it for the time being.
958
959    BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
960    That could be used to prefer certain servers fairly easily.  Maybe some
961    other time...
962
963    NOTE: this code is very system-dependent, and very dependent on the TCP/IP
964    protocols (well, addresses that are stored in uint32s, at any rate).
965  */
966
967 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
968 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
969
970 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
971 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
972 #define TOPR 5000
973 #define HI  20000
974 #define MED 30000
975 #define LO DEFRANK
976 #define PPWEIGHT 4096
977
978 #define USEIFADDR
979
980 #ifdef AFS_USERSPACE_IP_ADDR
981 #ifndef afs_min
982 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
983 #endif
984 /*
985  * The IP addresses and ranks are determined by afsd (in user space) and
986  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
987  * system call. These are stored in the data structure
988  * called 'afs_cb_interface'.
989  *
990  * struct srvAddr *sa;         remote server
991  * afs_int32 addr;                one of my local addr in net order
992  * afs_uint32 subnetmask;         subnet mask of local addr in net order
993  *
994  */
995 void
996 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
997                      afs_uint32 subnetmask)
998 {
999     afs_uint32 myAddr, myNet, mySubnet, netMask;
1000     afs_uint32 serverAddr;
1001
1002     myAddr = ntohl(addr);       /* one of my IP addr in host order */
1003     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1004     subnetmask = ntohl(subnetmask);     /* subnet mask in host order */
1005
1006     if (IN_CLASSA(myAddr))
1007         netMask = IN_CLASSA_NET;
1008     else if (IN_CLASSB(myAddr))
1009         netMask = IN_CLASSB_NET;
1010     else if (IN_CLASSC(myAddr))
1011         netMask = IN_CLASSC_NET;
1012     else
1013         netMask = 0;
1014
1015     myNet = myAddr & netMask;
1016     mySubnet = myAddr & subnetmask;
1017
1018     if ((serverAddr & netMask) == myNet) {
1019         if ((serverAddr & subnetmask) == mySubnet) {
1020             if (serverAddr == myAddr) { /* same machine */
1021                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1022             } else {            /* same subnet */
1023                 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1024             }
1025         } else {                /* same net */
1026             sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1027         }
1028     }
1029     return;
1030 }
1031 #else /* AFS_USERSPACE_IP_ADDR */
1032 #if (! defined(AFS_SUN5_ENV)) && (! defined(AFS_DARWIN_ENV)) && (! defined(AFS_OBSD47_ENV)) && (! defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1033 void
1034 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1035 {
1036     struct sockaddr_in *sin;
1037     int t;
1038
1039     if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1040         if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1041             sin = IA_SIN(ifa);
1042             if (SA2ULONG(sin) == ntohl(sa->sa_ip)) {    /* ie, ME!!!  */
1043                 sa->sa_iprank = TOPR;
1044             } else {
1045                 t = HI + ifa->ia_ifp->if_metric;        /* case #2 */
1046                 if (sa->sa_iprank > t)
1047                     sa->sa_iprank = t;
1048             }
1049         } else {
1050             t = MED + ifa->ia_ifp->if_metric;   /* case #3 */
1051             if (sa->sa_iprank > t)
1052                 sa->sa_iprank = t;
1053         }
1054     }
1055 #ifdef  IFF_POINTTOPOINT
1056     /* check for case #4 -- point-to-point link */
1057     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1058         && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1059         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1060             t = MAXDEFRANK;
1061         else
1062             t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1063         if (sa->sa_iprank > t)
1064             sa->sa_iprank = t;
1065     }
1066 #endif /* IFF_POINTTOPOINT */
1067 }
1068 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1069 #if (defined(AFS_DARWIN_ENV) || defined(AFS_OBSD47_ENV) || defined(AFS_FBSD_ENV)) && defined(USEIFADDR)
1070 #ifndef afs_min
1071 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1072 #endif
1073 void
1074 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1075 {
1076     struct sockaddr sout;
1077     struct sockaddr_in *sin;
1078 #if defined(AFS_DARWIN80_ENV) && !defined(UKERNEL)
1079     int t;
1080 #else
1081     void *t;
1082 #endif
1083
1084     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1085     afs_uint32 serverAddr;
1086
1087     if (rx_ifaddr_address_family(ifa) != AF_INET)
1088         return;
1089     t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1090     if (t != 0) {
1091         sin = (struct sockaddr_in *)&sout;
1092         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1093     } else {
1094         myAddr = 0;
1095     }
1096     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1097     t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1098     if (t != 0) {
1099         sin = (struct sockaddr_in *)&sout;
1100         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1101     } else {
1102         subnetmask = 0;
1103     }
1104     t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1105     if (t != 0) {
1106         sin = (struct sockaddr_in *)&sout;
1107         myDstaddr = ntohl(sin->sin_addr.s_addr);
1108     } else {
1109         myDstaddr = 0;
1110     }
1111
1112     if (IN_CLASSA(myAddr))
1113         netMask = IN_CLASSA_NET;
1114     else if (IN_CLASSB(myAddr))
1115         netMask = IN_CLASSB_NET;
1116     else if (IN_CLASSC(myAddr))
1117         netMask = IN_CLASSC_NET;
1118     else
1119         netMask = 0;
1120
1121     myNet = myAddr & netMask;
1122     mySubnet = myAddr & subnetmask;
1123
1124     if ((serverAddr & netMask) == myNet) {
1125         if ((serverAddr & subnetmask) == mySubnet) {
1126             if (serverAddr == myAddr) { /* same machine */
1127                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1128             } else {            /* same subnet */
1129                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1130             }
1131         } else {                /* same net */
1132             sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1133         }
1134     }
1135 #ifdef  IFF_POINTTOPOINT
1136     /* check for case #4 -- point-to-point link */
1137     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1138         && (myDstaddr == serverAddr)) {
1139         if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1140             t = MAXDEFRANK;
1141         else
1142             t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1143         if (sa->sa_iprank > t)
1144             sa->sa_iprank = t;
1145         }
1146 #endif /* IFF_POINTTOPOINT */
1147 }
1148 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1149 #endif /* else AFS_USERSPACE_IP_ADDR */
1150
1151 #ifdef AFS_SGI62_ENV
1152 static int
1153 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1154                    caddr_t arg2)
1155 {
1156     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1157     return 0;                   /* Never match, so we enumerate everyone */
1158 }
1159 #endif                          /* AFS_SGI62_ENV */
1160 static int
1161 afs_SetServerPrefs(struct srvAddr *sa)
1162 {
1163 #if     defined(AFS_USERSPACE_IP_ADDR)
1164     int i;
1165
1166       sa->sa_iprank = LO;
1167     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1168         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1169                              afs_cb_interface.subnetmask[i]);
1170     }
1171 #else                           /* AFS_USERSPACE_IP_ADDR */
1172 #if     defined(AFS_SUN5_ENV)
1173 #ifdef AFS_SUN510_ENV
1174     int i = 0;
1175 #else
1176     extern struct ill_s *ill_g_headp;
1177     long *addr = (long *)ill_g_headp;
1178     ill_t *ill;
1179     ipif_t *ipif;
1180 #endif
1181     int subnet, subnetmask, net, netmask;
1182
1183     if (sa)
1184           sa->sa_iprank = 0;
1185 #ifdef AFS_SUN510_ENV
1186     rw_enter(&afsifinfo_lock, RW_READER);
1187
1188     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1189
1190         if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1191             netmask = IN_CLASSA_NET;
1192         } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1193             netmask = IN_CLASSB_NET;
1194         } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1195             netmask = IN_CLASSC_NET;
1196         } else {
1197             netmask = 0;
1198         }
1199         net = afsifinfo[i].ipaddr & netmask;
1200
1201 #ifdef notdef
1202         if (!s) {
1203             if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) {      /* ignore loopback */
1204                 *cnt += 1;
1205                 if (*cnt > 16)
1206                     return;
1207                 *addrp++ = afsifinfo[i].ipaddr;
1208             }
1209         } else
1210 #endif /* notdef */
1211         {
1212             /* XXXXXX Do the individual ip ranking below XXXXX */
1213             if ((sa->sa_ip & netmask) == net) {
1214                 if ((sa->sa_ip & subnetmask) == subnet) {
1215                     if (afsifinfo[i].ipaddr == sa->sa_ip) {   /* ie, ME!  */
1216                         sa->sa_iprank = TOPR;
1217                     } else {
1218                         sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1219                     }
1220                 } else {
1221                     sa->sa_iprank = MED + afsifinfo[i].metric;    /* case #3 */
1222                 }
1223             } else {
1224                     sa->sa_iprank = LO + afsifinfo[i].metric;     /* case #4 */
1225             }
1226             /* check for case #5 -- point-to-point link */
1227             if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1228                 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1229
1230                     if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1231                         sa->sa_iprank = MAXDEFRANK;
1232                     else
1233                         sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1234             }
1235         }
1236     }
1237
1238     rw_exit(&afsifinfo_lock);
1239 #else
1240     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1241          ill = ill->ill_next) {
1242         /* Make sure this is an IPv4 ILL */
1243         if (ill->ill_isv6)
1244             continue;
1245         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1246             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1247             subnetmask = ipif->ipif_net_mask;
1248             /*
1249              * Generate the local net using the local address and
1250              * whate we know about Class A, B and C networks.
1251              */
1252             if (IN_CLASSA(ipif->ipif_local_addr)) {
1253                 netmask = IN_CLASSA_NET;
1254             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1255                 netmask = IN_CLASSB_NET;
1256             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1257                 netmask = IN_CLASSC_NET;
1258             } else {
1259                 netmask = 0;
1260             }
1261             net = ipif->ipif_local_addr & netmask;
1262 #ifdef notdef
1263             if (!s) {
1264                 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) {        /* ignore loopback */
1265                     *cnt += 1;
1266                     if (*cnt > 16)
1267                         return;
1268                     *addrp++ = ipif->ipif_local_addr;
1269                 }
1270             } else
1271 #endif /* notdef */
1272             {
1273                 /* XXXXXX Do the individual ip ranking below XXXXX */
1274                 if ((sa->sa_ip & netmask) == net) {
1275                     if ((sa->sa_ip & subnetmask) == subnet) {
1276                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1277                             sa->sa_iprank = TOPR;
1278                         } else {
1279                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1280                         }
1281                     } else {
1282                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1283                     }
1284                 } else {
1285                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1286                 }
1287                 /* check for case #5 -- point-to-point link */
1288                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1289                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1290
1291                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1292                         sa->sa_iprank = MAXDEFRANK;
1293                     else
1294                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1295                 }
1296             }
1297         }
1298     }
1299 #endif /* AFS_SUN510_ENV */
1300 #else
1301 #ifndef USEIFADDR
1302     rx_ifnet_t ifn = NULL;
1303     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1304     struct sockaddr_in *sin;
1305
1306     if (!sa) {
1307 #ifdef notdef                   /* clean up, remove this */
1308         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1309             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1310                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1311                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1312                     *cnt += 1;
1313                     if (*cnt > 16)
1314                         return;
1315                     *addrp++ =
1316                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1317                         s_addr;
1318                 }
1319         }}
1320 #endif                          /* notdef */
1321         return;
1322     }
1323     sa->sa_iprank = 0;
1324 #ifdef  ADAPT_MTU
1325     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1326 #endif
1327     if (ifn) {                  /* local, more or less */
1328 #ifdef IFF_LOOPBACK
1329         if (ifn->if_flags & IFF_LOOPBACK) {
1330             sa->sa_iprank = TOPR;
1331             goto end;
1332         }
1333 #endif /* IFF_LOOPBACK */
1334         sin = (struct sockaddr_in *)IA_SIN(ifad);
1335         if (SA2ULONG(sin) == sa->sa_ip) {
1336             sa->sa_iprank = TOPR;
1337             goto end;
1338         }
1339 #ifdef IFF_BROADCAST
1340         if (ifn->if_flags & IFF_BROADCAST) {
1341             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1342                 sa->sa_iprank = HI;
1343                 goto end;
1344             }
1345         }
1346 #endif /* IFF_BROADCAST */
1347 #ifdef IFF_POINTOPOINT
1348         if (ifn->if_flags & IFF_POINTOPOINT) {
1349             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1350                 if (ifn->if_metric > 4) {
1351                     sa->sa_iprank = LO;
1352                     goto end;
1353                 } else
1354                     sa->sa_iprank = ifn->if_metric;
1355             }
1356         }
1357 #endif /* IFF_POINTOPOINT */
1358         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1359     }
1360 #else                           /* USEIFADDR */
1361
1362     if (sa)
1363         sa->sa_iprank = LO;
1364 #ifdef AFS_SGI62_ENV
1365     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1366                     (caddr_t) sa, NULL);
1367 #elif defined(AFS_DARWIN80_ENV)
1368     {
1369         errno_t t;
1370         unsigned int count;
1371         int cnt=0, m, j;
1372         rx_ifaddr_t *ifads;
1373         rx_ifnet_t *ifns;
1374
1375         if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1376             for (m = 0; m < count; m++) {
1377                 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1378                     for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1379                         afsi_SetServerIPRank(sa, ifads[j]);
1380                         cnt++;
1381                     }
1382                     ifnet_free_address_list(ifads);
1383                 }
1384             }
1385             ifnet_list_free(ifns);
1386         }
1387     }
1388 #elif defined(AFS_DARWIN_ENV)
1389     {
1390         rx_ifnet_t ifn;
1391         rx_ifaddr_t ifa;
1392           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1393             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1394                 afsi_SetServerIPRank(sa, ifa);
1395     }}}
1396 #elif defined(AFS_FBSD_ENV)
1397     {
1398         struct in_ifaddr *ifa;
1399 #if defined(AFS_FBSD80_ENV)
1400           TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
1401 #else
1402           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1403 #endif
1404             afsi_SetServerIPRank(sa, &ifa->ia_ifa);
1405     }}
1406 #elif defined(AFS_OBSD_ENV)
1407     {
1408         extern struct in_ifaddrhead in_ifaddr;
1409         struct in_ifaddr *ifa;
1410         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1411             afsi_SetServerIPRank(sa, ifa);
1412     }
1413 #elif defined(AFS_NBSD40_ENV)
1414      {
1415        extern struct in_ifaddrhead in_ifaddrhead;
1416        struct in_ifaddr *ifa;
1417        for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1418            afsi_SetServerIPRank(sa, ifa);
1419      }
1420 #else
1421     {
1422         struct in_ifaddr *ifa;
1423         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1424             afsi_SetServerIPRank(sa, ifa);
1425     }}
1426 #endif
1427 #endif                          /* USEIFADDR */
1428 #ifndef USEIFADDR
1429     end:
1430 #endif
1431 #endif                          /* AFS_SUN5_ENV */
1432 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1433     if (sa)
1434           sa->sa_iprank += afs_randomMod15();
1435
1436     return 0;
1437 }                               /* afs_SetServerPrefs */
1438
1439 #undef TOPR
1440 #undef HI
1441 #undef MED
1442 #undef LO
1443 #undef PPWEIGHT
1444
1445 /* afs_FlushServer()
1446  * The addresses on this server struct has changed in some way and will
1447  * clean up all other structures that may reference it.
1448  * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
1449  */
1450 static void
1451 afs_FlushServer(struct server *srvp, struct volume *tv)
1452 {
1453     afs_int32 i;
1454     struct server *ts, **pts;
1455
1456     /* Find any volumes residing on this server and flush their state */
1457     afs_ResetVolumes(srvp, tv);
1458
1459     /* Flush all callbacks in the all vcaches for this specific server */
1460     afs_FlushServerCBs(srvp);
1461
1462     /* Remove all the callbacks structs */
1463     if (srvp->cbrs) {
1464         struct afs_cbr *cb, *cbnext;
1465
1466         for (cb = srvp->cbrs; cb; cb = cbnext) {
1467             cbnext = cb->next;
1468             afs_FreeCBR(cb);
1469         } srvp->cbrs = (struct afs_cbr *)0;
1470     }
1471
1472     /* If no more srvAddr structs hanging off of this server struct,
1473      * then clean it up.
1474      */
1475     if (!srvp->addr) {
1476         /* Remove the server structure from the cell list - if there */
1477         afs_RemoveCellEntry(srvp);
1478
1479         /* Remove from the afs_servers hash chain */
1480         for (i = 0; i < NSERVERS; i++) {
1481             for (pts = &(afs_servers[i]), ts = *pts; ts;
1482                  pts = &(ts->next), ts = *pts) {
1483                 if (ts == srvp)
1484                     break;
1485             }
1486             if (ts)
1487                 break;
1488         }
1489         if (ts) {
1490             *pts = ts->next;    /* Found it. Remove it */
1491             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1492             afs_totalServers--;
1493         }
1494     }
1495 }
1496
1497 /* afs_RemoveSrvAddr()
1498  * This removes a SrvAddr structure from its server structure.
1499  * The srvAddr struct is not free'd because it connections may still
1500  * be open to it. It is up to the calling process to make sure it
1501  * remains connected to a server struct.
1502  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1503  *    It is not removed from the afs_srvAddrs hash chain.
1504  * If resetting volumes, do not reset volume tv
1505  */
1506 static void
1507 afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
1508 {
1509     struct srvAddr **psa, *sa;
1510     struct server *srv;
1511
1512     if (!sap)
1513           return;
1514       srv = sap->server;
1515
1516     /* Find the srvAddr in the server's list and remove it */
1517     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1518         if (sa == sap)
1519             break;
1520     } if (sa) {
1521         *psa = sa->next_sa;
1522         sa->next_sa = 0;
1523         sa->server = 0;
1524
1525         /* Flush the server struct since it's IP address has changed */
1526         afs_FlushServer(srv, tv);
1527     }
1528 }
1529
1530 /* afs_GetCapabilities
1531  * Try and retrieve capabilities of a given file server. Carps on actual
1532  * failure. Servers are not expected to support this RPC. */
1533 void
1534 afs_GetCapabilities(struct server *ts)
1535 {
1536     Capabilities caps = {0, NULL};
1537     struct vrequest treq;
1538     struct afs_conn *tc;
1539     struct unixuser *tu;
1540     struct rx_connection *rxconn;
1541     afs_int32 code;
1542
1543     if ( !ts || !ts->cell )
1544         return;
1545     if ( !afs_osi_credp )
1546         return;
1547
1548     if ((code = afs_InitReq(&treq, afs_osi_credp)))
1549         return;
1550     tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1551     if ( !tu )
1552         return;
1553     tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1554                       SHARED_LOCK, 0, &rxconn);
1555     afs_PutUser(tu, SHARED_LOCK);
1556     if ( !tc )
1557         return;
1558     /* InitCallBackStateN, triggered by our RPC, may need this */
1559     ReleaseWriteLock(&afs_xserver);
1560     code = RXAFS_GetCapabilities(rxconn, &caps);
1561     ObtainWriteLock(&afs_xserver, 723);
1562     /* we forced a conn above; important we mark it down if needed */
1563     if ((code < 0) && (code != RXGEN_OPCODE)) {
1564         afs_ServerDown(tc->parent->srvr, code);
1565         ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1566     }
1567     afs_PutConn(tc, rxconn, SHARED_LOCK);
1568     if ( code && code != RXGEN_OPCODE ) {
1569         afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1570         /* better not be anything to free. we failed! */
1571         return;
1572     }
1573
1574     ts->flags |= SCAPS_KNOWN;
1575
1576     if ( caps.Capabilities_len > 0 ) {
1577         ts->capabilities = caps.Capabilities_val[0];
1578         xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1579         caps.Capabilities_len = 0;
1580         caps.Capabilities_val = NULL;
1581     }
1582
1583 }
1584
1585 static struct server *
1586 afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
1587                  struct server **oldts, afs_int32 addr_uniquifier)
1588 {
1589     struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
1590     if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1591         /* Found a server struct that is multihomed and same
1592          * uniqufier (same IP addrs). The above if statement is the
1593          * same as in InstallUVolumeEntry().
1594          */
1595         return ts;
1596     }
1597     if (ts)
1598         *oldts = ts;            /* Will reuse if same uuid */
1599     return NULL;
1600 }
1601
1602 /*!
1603  * Return an updated and properly initialized server structure.
1604  *
1605  * Takes a server ID, cell, and port.
1606  * If server does not exist, then one will be created.
1607  * @param[in] aserverp
1608  *      The server address in network byte order
1609  * @param[in] nservers
1610  *      The number of IP addresses claimed by the server
1611  * @param[in] acell
1612  *      The cell the server is in
1613  * @param[in] aport
1614  *      The port for the server (fileserver or vlserver) in network byte order
1615  * @param[in] locktype
1616  *      The type of lock to hold when iterating server hash (unused).
1617  * @param[in] uuidp
1618  *      The uuid for servers supporting one.
1619  * @param[in] addr_uniquifier
1620  *      The vldb-provider per-instantiated-server uniquifer counter.
1621  * @param[in] tv
1622  *      A volume not to reset information for if the server addresses
1623  *      changed.
1624  *
1625  * @return
1626  *      A server structure matching the request.
1627  */
1628 struct server *
1629 afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
1630               u_short aport, afs_int32 locktype, afsUUID * uuidp,
1631               afs_int32 addr_uniquifier, struct volume *tv)
1632 {
1633     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1634     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1635     afs_int32 iphash, k, srvcount = 0;
1636     unsigned int srvhash;
1637
1638     AFS_STATCNT(afs_GetServer);
1639
1640     ObtainSharedLock(&afs_xserver, 13);
1641
1642     /* Check if the server struct exists and is up to date */
1643     if (!uuidp) {
1644         if (nservers != 1)
1645             panic("afs_GetServer: incorrect count of servers");
1646         ObtainReadLock(&afs_xsrvAddr);
1647         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1648         ReleaseReadLock(&afs_xsrvAddr);
1649         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1650             /* Found a server struct that is not multihomed and has the
1651              * IP address associated with it. A correct match.
1652              */
1653             ReleaseSharedLock(&afs_xserver);
1654             return (ts);
1655         }
1656     } else {
1657         if (nservers <= 0)
1658             panic("afs_GetServer: incorrect count of servers");
1659
1660         ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
1661         if (ts) {
1662             ReleaseSharedLock(&afs_xserver);
1663             return ts;
1664         }
1665     }
1666
1667     /*
1668      * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
1669      * Do a little dance and see if we can grab xvcb. If not, we
1670      * need to recheck that oldts is still right after a drop and reobtain.
1671      */
1672     if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
1673         ReleaseSharedLock(&afs_xserver);
1674         ObtainWriteLock(&afs_xvcb, 299);
1675         ObtainWriteLock(&afs_xserver, 35);
1676
1677         /* we don't know what changed while we didn't hold the lock */
1678         oldts = 0;
1679         ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
1680                               addr_uniquifier);
1681         if (ts) {
1682             ReleaseWriteLock(&afs_xserver);
1683             ReleaseWriteLock(&afs_xvcb);
1684             return ts;
1685         }
1686     } else {
1687         UpgradeSToWLock(&afs_xserver, 36);
1688     }
1689     ObtainWriteLock(&afs_xsrvAddr, 116);
1690     srvcount = afs_totalServers;
1691
1692     /* Reuse/allocate a new server structure */
1693     if (oldts) {
1694         newts = oldts;
1695     } else {
1696         newts = afs_osi_Alloc(sizeof(struct server));
1697         if (!newts)
1698             panic("malloc of server struct");
1699         afs_totalServers++;
1700         memset(newts, 0, sizeof(struct server));
1701
1702         /* Add the server struct to the afs_servers[] hash chain */
1703         srvhash =
1704             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1705         newts->next = afs_servers[srvhash];
1706         afs_servers[srvhash] = newts;
1707     }
1708
1709     /* Initialize the server structure */
1710     if (uuidp) {                /* Multihomed */
1711         newts->sr_uuid = *uuidp;
1712         newts->sr_addr_uniquifier = addr_uniquifier;
1713         newts->flags |= SRVR_MULTIHOMED;
1714     }
1715     if (acell)
1716         newts->cell = afs_GetCell(acell, 0);
1717
1718     /* For each IP address we are registering */
1719     for (k = 0; k < nservers; k++) {
1720         iphash = SHash(aserverp[k]);
1721
1722         /* Check if the srvAddr structure already exists. If so, remove
1723          * it from its server structure and add it to the new one.
1724          */
1725         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1726             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1727                 break;
1728         }
1729         if (oldsa && (oldsa->server != newts)) {
1730             afs_RemoveSrvAddr(oldsa, tv);       /* Remove from its server struct */
1731             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1732             newts->addr = oldsa;
1733         }
1734
1735         /* Reuse/allocate a new srvAddr structure */
1736         if (oldsa) {
1737             newsa = oldsa;
1738         } else {
1739             newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1740             if (!newsa)
1741                 panic("malloc of srvAddr struct");
1742             afs_totalSrvAddrs++;
1743             memset(newsa, 0, sizeof(struct srvAddr));
1744
1745             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1746             newsa->next_bkt = afs_srvAddrs[iphash];
1747             afs_srvAddrs[iphash] = newsa;
1748
1749             /* Hang off of the server structure  */
1750             newsa->next_sa = newts->addr;
1751             newts->addr = newsa;
1752
1753             /* Initialize the srvAddr Structure */
1754             newsa->sa_ip = aserverp[k];
1755             newsa->sa_portal = aport;
1756         }
1757
1758         /* Update the srvAddr Structure */
1759         newsa->server = newts;
1760         if (newts->flags & SRVR_ISDOWN)
1761             newsa->sa_flags |= SRVADDR_ISDOWN;
1762         if (uuidp)
1763             newsa->sa_flags |= SRVADDR_MH;
1764         else
1765             newsa->sa_flags &= ~SRVADDR_MH;
1766
1767         /* Compute preference values and resort */
1768         if (!newsa->sa_iprank) {
1769             afs_SetServerPrefs(newsa);  /* new server rank */
1770         }
1771     }
1772     afs_SortOneServer(newts);   /* Sort by rank */
1773
1774     /* If we reused the server struct, remove any of its srvAddr
1775      * structs that will no longer be associated with this server.
1776      */
1777     if (oldts) {                /* reused the server struct */
1778         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1779             nextsa = orphsa->next_sa;
1780             for (k = 0; k < nservers; k++) {
1781                 if (orphsa->sa_ip == aserverp[k])
1782                     break;      /* belongs */
1783             }
1784             if (k < nservers)
1785                 continue;       /* belongs */
1786
1787             /* Have a srvAddr struct. Now get a server struct (if not already) */
1788             if (!orphts) {
1789                 orphts = afs_osi_Alloc(sizeof(struct server));
1790                 if (!orphts)
1791                     panic("malloc of lo server struct");
1792                 memset(orphts, 0, sizeof(struct server));
1793                 afs_totalServers++;
1794
1795                 /* Add the orphaned server to the afs_servers[] hash chain.
1796                  * Its iphash does not matter since we never look up the server
1797                  * in the afs_servers table by its ip address (only by uuid -
1798                  * which this has none).
1799                  */
1800                 iphash = SHash(aserverp[k]);
1801                 orphts->next = afs_servers[iphash];
1802                 afs_servers[iphash] = orphts;
1803
1804                 if (acell)
1805                     orphts->cell = afs_GetCell(acell, 0);
1806             }
1807
1808             /* Hang the srvAddr struct off of the server structure. The server
1809              * may have multiple srvAddrs, but it won't be marked multihomed.
1810              */
1811             afs_RemoveSrvAddr(orphsa, tv);      /* remove */
1812             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1813             orphts->addr = orphsa;
1814             orphsa->server = orphts;
1815             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1816             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1817         }
1818     }
1819     /* We can't need this below, and won't reacquire */
1820     ReleaseWriteLock(&afs_xvcb);
1821
1822     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1823     if (srvcount) {
1824         struct afs_stats_SrvUpDownInfo *upDownP;
1825         /* With the introduction of this new record, we need to adjust the
1826          * proper individual & global server up/down info.
1827          */
1828         upDownP = GetUpDownStats(newts);
1829         upDownP->numTtlRecords += srvcount;
1830         afs_stats_cmperf.srvRecords += srvcount;
1831         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1832             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1833     }
1834     /* We can't need this below, and won't reacquire */
1835     ReleaseWriteLock(&afs_xvcb);
1836
1837     ReleaseWriteLock(&afs_xsrvAddr);
1838
1839     if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1840         afs_GetCapabilities(newts);
1841
1842     ReleaseWriteLock(&afs_xserver);
1843     return (newts);
1844 }                               /* afs_GetServer */
1845
1846 void
1847 afs_ActivateServer(struct srvAddr *sap)
1848 {
1849     osi_timeval_t currTime;     /*Filled with current time */
1850     osi_timeval_t *currTimeP;   /*Ptr to above */
1851     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1852     struct server *aserver = sap->server;
1853
1854     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1855         /*
1856          * This server record has not yet been activated.  Go for it,
1857          * recording its ``birth''.
1858          */
1859         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1860         currTimeP = &currTime;
1861         osi_GetuTime(currTimeP);
1862         aserver->activationTime = currTime.tv_sec;
1863         upDownP = GetUpDownStats(aserver);
1864         if (aserver->flags & SRVR_ISDOWN) {
1865             upDownP->numDownRecords++;
1866         } else {
1867             upDownP->numUpRecords++;
1868             upDownP->numRecordsNeverDown++;
1869         }
1870     }
1871 }
1872
1873 void
1874 afs_RemoveAllConns(void)
1875 {
1876     int i;
1877     struct server *ts, *nts;
1878     struct srvAddr *sa;
1879
1880     ObtainReadLock(&afs_xserver);
1881     ObtainWriteLock(&afs_xconn, 1001);
1882
1883     /*printf("Destroying connections ... ");*/
1884     for (i = 0; i < NSERVERS; i++) {
1885         for (ts = afs_servers[i]; ts; ts = nts) {
1886             nts = ts->next;
1887             for (sa = ts->addr; sa; sa = sa->next_sa) {
1888                 if (sa->conns) {
1889                     afs_ReleaseConns(sa->conns);
1890                     sa->conns = NULL;
1891                 }
1892             }
1893         }
1894     }
1895     /*printf("done\n");*/
1896
1897     ReleaseWriteLock(&afs_xconn);
1898     ReleaseReadLock(&afs_xserver);
1899
1900 }
1901
1902 void
1903 afs_MarkAllServersUp(void)
1904 {
1905     int i;
1906     struct server *ts;
1907     struct srvAddr *sa;
1908
1909     ObtainWriteLock(&afs_xserver, 721);
1910     ObtainWriteLock(&afs_xsrvAddr, 722);
1911     for (i = 0; i< NSERVERS; i++) {
1912         for (ts = afs_servers[i]; ts; ts = ts->next) {
1913             for (sa = ts->addr; sa; sa = sa->next_sa) {
1914                 afs_MarkServerUpOrDown(sa, 0);
1915             }
1916         }
1917     }
1918     ReleaseWriteLock(&afs_xsrvAddr);
1919     ReleaseWriteLock(&afs_xserver);
1920 }