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