afs: fix afs_xserver deadlock in afsdb refresh
[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, struct rx_connection *rxconn)
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("afs: Lost contact with volume location server ",
243                               sa, "", 1, code, rxconn);
244     else
245         print_internet_address("afs: Lost contact with file server ", sa, "",
246                                1, code, rxconn);
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     /*
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, rxconn);
313         }
314     }
315     afs_PutConn(tc, rxconn, SHARED_LOCK);
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, struct rx_connection **rxconns,
522                  int nconns, afs_int32 *results)
523 {
524     struct srvAddr *sa;
525     struct afs_conn *tc;
526     afs_int32 i;
527
528     for(i = 0; i < nconns; i++){
529         tc = conns[i];
530         sa = tc->parent->srvr;
531
532         if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) &&
533             (tc->parent->srvr == sa)) {
534             /* server back up */
535             print_internet_address("afs: file server ", sa, " is back up", 2,
536                                    results[i], rxconns[i]);
537
538             ObtainWriteLock(&afs_xserver, 244);
539             ObtainWriteLock(&afs_xsrvAddr, 245);
540             afs_MarkServerUpOrDown(sa, 0);
541             ReleaseWriteLock(&afs_xsrvAddr);
542             ReleaseWriteLock(&afs_xserver);
543
544             if (afs_waitForeverCount) {
545                 afs_osi_Wakeup(&afs_waitForever);
546             }
547         } else {
548             if (results[i] < 0) {
549                 /* server crashed */
550                 afs_ServerDown(sa, results[i], rxconns[i]);
551                 ForceNewConnections(sa);  /* multi homed clients */
552             }
553         }
554     }
555 }
556
557 void
558 CkSrv_GetCaps(int nconns, struct rx_connection **rxconns,
559               struct afs_conn **conns)
560 {
561     Capabilities *caps;
562     afs_int32 *results;
563     afs_int32 i;
564     struct server *ts;
565
566     caps = afs_osi_Alloc(nconns * sizeof (Capabilities));
567     osi_Assert(caps != NULL);
568     memset(caps, 0, nconns * sizeof(Capabilities));
569
570     results = afs_osi_Alloc(nconns * sizeof (afs_int32));
571     osi_Assert(results != NULL);
572
573     AFS_GUNLOCK();
574     multi_Rx(rxconns,nconns)
575       {
576         multi_RXAFS_GetCapabilities(&caps[multi_i]);
577         results[multi_i] = multi_error;
578       } multi_End;
579     AFS_GLOCK();
580
581     for ( i = 0 ; i < nconns ; i++ ) {
582         ts = conns[i]->parent->srvr->server;
583         if ( !ts )
584             continue;
585         ts->capabilities = 0;
586         ts->flags |= SCAPS_KNOWN;
587         if ( results[i] == RXGEN_OPCODE ) {
588             /* Mark server as up - it responded */
589             results[i] = 0;
590             continue;
591         }
592         if ( results[i] >= 0 )
593             /* we currently handle 32-bits of capabilities */
594             if (caps[i].Capabilities_len > 0) {
595                 ts->capabilities = caps[i].Capabilities_val[0];
596                 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
597                 caps[i].Capabilities_val = NULL;
598                 caps[i].Capabilities_len = 0;
599             }
600     }
601     CkSrv_MarkUpDown(conns, rxconns, nconns, results);
602
603     afs_osi_Free(caps, nconns * sizeof(Capabilities));
604     afs_osi_Free(results, nconns * sizeof(afs_int32));
605 }
606
607 /* check down servers (if adown), or running servers (if !adown) */
608 void
609 afs_CheckServers(int adown, struct cell *acellp)
610 {
611     afs_LoopServers(adown?AFS_LS_DOWN:AFS_LS_UP, acellp, 1, CkSrv_GetCaps, NULL);
612 }
613
614 /* adown: AFS_LS_UP   - check only up
615  *        AFS_LS_DOWN - check only down.
616  *        AFS_LS_ALL  - check all */
617 void
618 afs_LoopServers(int adown, struct cell *acellp, int vlalso,
619                 void (*func1) (int nservers, struct rx_connection **rxconns,
620                                struct afs_conn **conns),
621                 void (*func2) (int nservers, struct rx_connection **rxconns,
622                                struct afs_conn **conns))
623 {
624     struct vrequest *treq = NULL;
625     struct server *ts;
626     struct srvAddr *sa;
627     struct afs_conn *tc = NULL;
628     afs_int32 i, j;
629     afs_int32 code;
630     struct unixuser *tu;
631     int srvAddrCount;
632     struct srvAddr **addrs;
633     struct afs_conn **conns;
634     int nconns;
635     struct rx_connection **rxconns;
636     afs_int32 *conntimer;
637
638     AFS_STATCNT(afs_CheckServers);
639
640     /*
641      * No sense in doing the server checks if we are running in disconnected
642      * mode
643      */
644     if (AFS_IS_DISCONNECTED)
645         return;
646
647     if ((code = afs_CreateReq(&treq, afs_osi_credp)))
648         return;
649     ObtainReadLock(&afs_xserver);       /* Necessary? */
650     ObtainReadLock(&afs_xsrvAddr);
651
652     srvAddrCount = 0;
653     for (i = 0; i < NSERVERS; i++) {
654         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
655             srvAddrCount++;
656         }
657     }
658
659     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
660     osi_Assert(addrs != NULL);
661     j = 0;
662     for (i = 0; i < NSERVERS; i++) {
663         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
664             if (j >= srvAddrCount)
665                 break;
666             addrs[j++] = sa;
667         }
668     }
669
670     ReleaseReadLock(&afs_xsrvAddr);
671     ReleaseReadLock(&afs_xserver);
672
673     conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
674     osi_Assert(conns != NULL);
675     rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
676     osi_Assert(rxconns != NULL);
677     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
678     osi_Assert(conntimer != NULL);
679
680     nconns = 0;
681     for (i = 0; i < j; i++) {
682         struct rx_connection *rxconn;
683         sa = addrs[i];
684         ts = sa->server;
685         if (!ts)
686             continue;
687
688         /* See if a cell to check was specified.  If it is spec'd and not
689          * this server's cell, just skip the server.
690          */
691         if (acellp && acellp != ts->cell)
692             continue;
693
694         if (((adown==AFS_LS_DOWN) && !(sa->sa_flags & SRVADDR_ISDOWN))
695             || ((adown==AFS_LS_UP) && (sa->sa_flags & SRVADDR_ISDOWN)))
696             continue;
697
698         /* check vlserver with special code */
699         if (sa->sa_portal == AFS_VLPORT) {
700             if (vlalso)
701                 CheckVLServer(sa, treq);
702             continue;
703         }
704
705         if (!ts->cell)          /* not really an active server, anyway, it must */
706             continue;           /* have just been added by setsprefs */
707
708         /* get a connection, even if host is down; bumps conn ref count */
709         tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
710         tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
711                           1 /*force */ , 1 /*create */ , SHARED_LOCK, 0,
712                           &rxconn);
713         afs_PutUser(tu, SHARED_LOCK);
714         if (!tc)
715             continue;
716
717         if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)) {
718             conns[nconns]=tc;
719             rxconns[nconns]=rxconn;
720             if (sa->sa_flags & SRVADDR_ISDOWN) {
721                 rx_SetConnDeadTime(rxconn, 3);
722                 conntimer[nconns]=1;
723             } else {
724                 conntimer[nconns]=0;
725             }
726             nconns++;
727         } else /* not holding, kill ref */
728             afs_PutConn(tc, rxconn, SHARED_LOCK);
729     } /* Outer loop over addrs */
730
731     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
732     addrs = NULL;
733
734     (*func1)(nconns, rxconns, conns);
735
736     if (func2) {
737         (*func2)(nconns, rxconns, conns);
738     }
739
740     for (i = 0; i < nconns; i++) {
741         if (conntimer[i] == 1)
742             rx_SetConnDeadTime(rxconns[i], afs_rx_deadtime);
743         afs_PutConn(conns[i], rxconns[i], SHARED_LOCK);     /* done with it now */
744     }
745
746     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
747     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
748     afs_osi_Free(conntimer, j * sizeof(afs_int32));
749     afs_DestroyReq(treq);
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 #if defined(IFF_POINTOPOINT) && !defined(UKERNEL)
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_POINTOPOINT */
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 *const 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     sa->sa_iprank = 0;
1182 #ifdef AFS_SUN510_ENV
1183     rw_enter(&afsifinfo_lock, RW_READER);
1184
1185     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1186
1187         if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1188             netmask = IN_CLASSA_NET;
1189         } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1190             netmask = IN_CLASSB_NET;
1191         } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1192             netmask = IN_CLASSC_NET;
1193         } else {
1194             netmask = 0;
1195         }
1196         net = afsifinfo[i].ipaddr & netmask;
1197
1198         {
1199             /* XXXXXX Do the individual ip ranking below XXXXX */
1200             if ((sa->sa_ip & netmask) == net) {
1201                 if ((sa->sa_ip & subnetmask) == subnet) {
1202                     if (afsifinfo[i].ipaddr == sa->sa_ip) {   /* ie, ME!  */
1203                         sa->sa_iprank = TOPR;
1204                     } else {
1205                         sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1206                     }
1207                 } else {
1208                     sa->sa_iprank = MED + afsifinfo[i].metric;    /* case #3 */
1209                 }
1210             } else {
1211                     sa->sa_iprank = LO + afsifinfo[i].metric;     /* case #4 */
1212             }
1213             /* check for case #5 -- point-to-point link */
1214             if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1215                 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1216
1217                     if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1218                         sa->sa_iprank = MAXDEFRANK;
1219                     else
1220                         sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1221             }
1222         }
1223     }
1224
1225     rw_exit(&afsifinfo_lock);
1226 #else
1227     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1228          ill = ill->ill_next) {
1229         /* Make sure this is an IPv4 ILL */
1230         if (ill->ill_isv6)
1231             continue;
1232         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1233             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1234             subnetmask = ipif->ipif_net_mask;
1235             /*
1236              * Generate the local net using the local address and
1237              * whate we know about Class A, B and C networks.
1238              */
1239             if (IN_CLASSA(ipif->ipif_local_addr)) {
1240                 netmask = IN_CLASSA_NET;
1241             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1242                 netmask = IN_CLASSB_NET;
1243             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1244                 netmask = IN_CLASSC_NET;
1245             } else {
1246                 netmask = 0;
1247             }
1248             net = ipif->ipif_local_addr & netmask;
1249             {
1250                 /* XXXXXX Do the individual ip ranking below XXXXX */
1251                 if ((sa->sa_ip & netmask) == net) {
1252                     if ((sa->sa_ip & subnetmask) == subnet) {
1253                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1254                             sa->sa_iprank = TOPR;
1255                         } else {
1256                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1257                         }
1258                     } else {
1259                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1260                     }
1261                 } else {
1262                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1263                 }
1264                 /* check for case #5 -- point-to-point link */
1265                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1266                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1267
1268                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1269                         sa->sa_iprank = MAXDEFRANK;
1270                     else
1271                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1272                 }
1273             }
1274         }
1275     }
1276 #endif /* AFS_SUN510_ENV */
1277 #else
1278 #ifndef USEIFADDR
1279     rx_ifnet_t ifn = NULL;
1280     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1281     struct sockaddr_in *sin;
1282
1283     sa->sa_iprank = 0;
1284     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1285     if (ifn) {                  /* local, more or less */
1286 #ifdef IFF_LOOPBACK
1287         if (ifn->if_flags & IFF_LOOPBACK) {
1288             sa->sa_iprank = TOPR;
1289             goto end;
1290         }
1291 #endif /* IFF_LOOPBACK */
1292         sin = (struct sockaddr_in *)IA_SIN(ifad);
1293         if (SA2ULONG(sin) == sa->sa_ip) {
1294             sa->sa_iprank = TOPR;
1295             goto end;
1296         }
1297 #ifdef IFF_BROADCAST
1298         if (ifn->if_flags & IFF_BROADCAST) {
1299             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1300                 sa->sa_iprank = HI;
1301                 goto end;
1302             }
1303         }
1304 #endif /* IFF_BROADCAST */
1305 #ifdef IFF_POINTOPOINT
1306         if (ifn->if_flags & IFF_POINTOPOINT) {
1307             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1308                 if (ifn->if_metric > 4) {
1309                     sa->sa_iprank = LO;
1310                     goto end;
1311                 } else
1312                     sa->sa_iprank = ifn->if_metric;
1313             }
1314         }
1315 #endif /* IFF_POINTOPOINT */
1316         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1317     }
1318 #else                           /* USEIFADDR */
1319
1320     sa->sa_iprank = LO;
1321 #ifdef AFS_SGI62_ENV
1322     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1323                     (caddr_t) sa, NULL);
1324 #elif defined(AFS_DARWIN80_ENV)
1325     {
1326         errno_t t;
1327         unsigned int count;
1328         int cnt=0, m, j;
1329         rx_ifaddr_t *ifads;
1330         rx_ifnet_t *ifns;
1331
1332         if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1333             for (m = 0; m < count; m++) {
1334                 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1335                     for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1336                         afsi_SetServerIPRank(sa, ifads[j]);
1337                         cnt++;
1338                     }
1339                     ifnet_free_address_list(ifads);
1340                 }
1341             }
1342             ifnet_list_free(ifns);
1343         }
1344     }
1345 #elif defined(AFS_DARWIN_ENV)
1346     {
1347         rx_ifnet_t ifn;
1348         rx_ifaddr_t ifa;
1349           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1350             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1351                 afsi_SetServerIPRank(sa, ifa);
1352     }}}
1353 #elif defined(AFS_FBSD_ENV)
1354     {
1355         struct in_ifaddr *ifa;
1356 #if defined(AFS_FBSD80_ENV)
1357           TAILQ_FOREACH(ifa, &V_in_ifaddrhead, ia_link) {
1358 #else
1359           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1360 #endif
1361             afsi_SetServerIPRank(sa, &ifa->ia_ifa);
1362     }}
1363 #elif defined(AFS_OBSD_ENV)
1364     {
1365         extern struct in_ifaddrhead in_ifaddr;
1366         struct in_ifaddr *ifa;
1367         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1368             afsi_SetServerIPRank(sa, ifa);
1369     }
1370 #elif defined(AFS_NBSD40_ENV)
1371      {
1372        extern struct in_ifaddrhead in_ifaddrhead;
1373        struct in_ifaddr *ifa;
1374        for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1375            afsi_SetServerIPRank(sa, ifa);
1376      }
1377 #else
1378     {
1379         struct in_ifaddr *ifa;
1380         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1381             afsi_SetServerIPRank(sa, ifa);
1382     }}
1383 #endif
1384 #endif                          /* USEIFADDR */
1385 #ifndef USEIFADDR
1386     end:
1387 #endif
1388 #endif                          /* AFS_SUN5_ENV */
1389 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1390     sa->sa_iprank += afs_randomMod15();
1391
1392     return 0;
1393 }                               /* afs_SetServerPrefs */
1394
1395 #undef TOPR
1396 #undef HI
1397 #undef MED
1398 #undef LO
1399 #undef PPWEIGHT
1400
1401 /* afs_FlushServer()
1402  * The addresses on this server struct has changed in some way and will
1403  * clean up all other structures that may reference it.
1404  * The afs_xserver, afs_xvcb and afs_xsrvAddr locks are assumed taken.
1405  */
1406 static void
1407 afs_FlushServer(struct server *srvp, struct volume *tv)
1408 {
1409     afs_int32 i;
1410     struct server *ts, **pts;
1411
1412     /* Find any volumes residing on this server and flush their state */
1413     afs_ResetVolumes(srvp, tv);
1414
1415     /* Flush all callbacks in the all vcaches for this specific server */
1416     afs_FlushServerCBs(srvp);
1417
1418     /* Remove all the callbacks structs */
1419     if (srvp->cbrs) {
1420         struct afs_cbr *cb, *cbnext;
1421
1422         for (cb = srvp->cbrs; cb; cb = cbnext) {
1423             cbnext = cb->next;
1424             afs_FreeCBR(cb);
1425         } srvp->cbrs = (struct afs_cbr *)0;
1426     }
1427
1428     /* If no more srvAddr structs hanging off of this server struct,
1429      * then clean it up.
1430      */
1431     if (!srvp->addr) {
1432         /* Remove the server structure from the cell list - if there */
1433         afs_RemoveCellEntry(srvp);
1434
1435         /* Remove from the afs_servers hash chain */
1436         for (i = 0; i < NSERVERS; i++) {
1437             for (pts = &(afs_servers[i]), ts = *pts; ts;
1438                  pts = &(ts->next), ts = *pts) {
1439                 if (ts == srvp)
1440                     break;
1441             }
1442             if (ts)
1443                 break;
1444         }
1445         if (ts) {
1446             *pts = ts->next;    /* Found it. Remove it */
1447             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1448             afs_totalServers--;
1449         }
1450     }
1451 }
1452
1453 /* afs_RemoveSrvAddr()
1454  * This removes a SrvAddr structure from its server structure.
1455  * The srvAddr struct is not free'd because it connections may still
1456  * be open to it. It is up to the calling process to make sure it
1457  * remains connected to a server struct.
1458  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1459  *    It is not removed from the afs_srvAddrs hash chain.
1460  * If resetting volumes, do not reset volume tv
1461  */
1462 static void
1463 afs_RemoveSrvAddr(struct srvAddr *sap, struct volume *tv)
1464 {
1465     struct srvAddr **psa, *sa;
1466     struct server *srv;
1467
1468     if (!sap)
1469           return;
1470       srv = sap->server;
1471
1472     /* Find the srvAddr in the server's list and remove it */
1473     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1474         if (sa == sap)
1475             break;
1476     } if (sa) {
1477         *psa = sa->next_sa;
1478         sa->next_sa = 0;
1479         sa->server = 0;
1480
1481         /* Flush the server struct since it's IP address has changed */
1482         afs_FlushServer(srv, tv);
1483     }
1484 }
1485
1486 /* afs_GetCapabilities
1487  * Try and retrieve capabilities of a given file server. Carps on actual
1488  * failure. Servers are not expected to support this RPC. */
1489 void
1490 afs_GetCapabilities(struct server *ts)
1491 {
1492     Capabilities caps = {0, NULL};
1493     struct vrequest *treq = NULL;
1494     struct afs_conn *tc;
1495     struct unixuser *tu;
1496     struct rx_connection *rxconn;
1497     afs_int32 code;
1498
1499     if ( !ts || !ts->cell )
1500         return;
1501     if ( !afs_osi_credp )
1502         return;
1503
1504     if ((code = afs_CreateReq(&treq, afs_osi_credp)))
1505         return;
1506     tu = afs_GetUser(treq->uid, ts->cell->cellNum, SHARED_LOCK);
1507     if ( !tu ) {
1508         afs_DestroyReq(treq);
1509         return;
1510     }
1511     tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1512                       SHARED_LOCK, 0, &rxconn);
1513     afs_PutUser(tu, SHARED_LOCK);
1514     if ( !tc ) {
1515         afs_DestroyReq(treq);
1516         return;
1517     }
1518     /* InitCallBackStateN, triggered by our RPC, may need this */
1519     ReleaseWriteLock(&afs_xserver);
1520     code = RXAFS_GetCapabilities(rxconn, &caps);
1521     ObtainWriteLock(&afs_xserver, 723);
1522     /* we forced a conn above; important we mark it down if needed */
1523     if ((code < 0) && (code != RXGEN_OPCODE)) {
1524         afs_ServerDown(tc->parent->srvr, code, rxconn);
1525         ForceNewConnections(tc->parent->srvr); /* multi homed clients */
1526     }
1527     afs_PutConn(tc, rxconn, SHARED_LOCK);
1528     if ( code && code != RXGEN_OPCODE ) {
1529         afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1530         /* better not be anything to free. we failed! */
1531         afs_DestroyReq(treq);
1532         return;
1533     }
1534
1535     ts->flags |= SCAPS_KNOWN;
1536
1537     if ( caps.Capabilities_len > 0 ) {
1538         ts->capabilities = caps.Capabilities_val[0];
1539         xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1540         caps.Capabilities_len = 0;
1541         caps.Capabilities_val = NULL;
1542     }
1543
1544     afs_DestroyReq(treq);
1545 }
1546
1547 static struct server *
1548 afs_SearchServer(u_short aport, afsUUID * uuidp, afs_int32 locktype,
1549                  struct server **oldts, afs_int32 addr_uniquifier)
1550 {
1551     struct server *ts = afs_FindServer(0, aport, uuidp, locktype);
1552     if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1553         /* Found a server struct that is multihomed and same
1554          * uniqufier (same IP addrs). The above if statement is the
1555          * same as in InstallUVolumeEntry().
1556          */
1557         return ts;
1558     }
1559     if (ts)
1560         *oldts = ts;            /* Will reuse if same uuid */
1561     return NULL;
1562 }
1563
1564 /*!
1565  * Return an updated and properly initialized server structure.
1566  *
1567  * Takes a server ID, cell, and port.
1568  * If server does not exist, then one will be created.
1569  * @param[in] aserverp
1570  *      The server address in network byte order
1571  * @param[in] nservers
1572  *      The number of IP addresses claimed by the server
1573  * @param[in] acell
1574  *      The cell the server is in
1575  * @param[in] aport
1576  *      The port for the server (fileserver or vlserver) in network byte order
1577  * @param[in] locktype
1578  *      The type of lock to hold when iterating server hash (unused).
1579  * @param[in] uuidp
1580  *      The uuid for servers supporting one.
1581  * @param[in] addr_uniquifier
1582  *      The vldb-provider per-instantiated-server uniquifer counter.
1583  * @param[in] tv
1584  *      A volume not to reset information for if the server addresses
1585  *      changed.
1586  *
1587  * @return
1588  *      A server structure matching the request.
1589  */
1590 struct server *
1591 afs_GetServer(afs_uint32 *aserverp, afs_int32 nservers, afs_int32 acell,
1592               u_short aport, afs_int32 locktype, afsUUID * uuidp,
1593               afs_int32 addr_uniquifier, struct volume *tv)
1594 {
1595     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1596     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1597     afs_int32 iphash, k, srvcount = 0;
1598     unsigned int srvhash;
1599
1600     AFS_STATCNT(afs_GetServer);
1601
1602     ObtainSharedLock(&afs_xserver, 13);
1603
1604     /* Check if the server struct exists and is up to date */
1605     if (!uuidp) {
1606         if (nservers != 1)
1607             panic("afs_GetServer: incorrect count of servers");
1608         ObtainReadLock(&afs_xsrvAddr);
1609         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1610         ReleaseReadLock(&afs_xsrvAddr);
1611         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1612             /* Found a server struct that is not multihomed and has the
1613              * IP address associated with it. A correct match.
1614              */
1615             ReleaseSharedLock(&afs_xserver);
1616             return (ts);
1617         }
1618     } else {
1619         if (nservers <= 0)
1620             panic("afs_GetServer: incorrect count of servers");
1621
1622         ts = afs_SearchServer(aport, uuidp, locktype, &oldts, addr_uniquifier);
1623         if (ts) {
1624             ReleaseSharedLock(&afs_xserver);
1625             return ts;
1626         }
1627     }
1628
1629     /*
1630      * Lock hierarchy requires xvcb, then xserver. We *have* xserver.
1631      * Do a little dance and see if we can grab xvcb. If not, we
1632      * need to recheck that oldts is still right after a drop and reobtain.
1633      */
1634     if (EWOULDBLOCK == NBObtainWriteLock(&afs_xvcb, 300)) {
1635         ReleaseSharedLock(&afs_xserver);
1636         ObtainWriteLock(&afs_xvcb, 299);
1637         ObtainWriteLock(&afs_xserver, 35);
1638
1639         /* we don't know what changed while we didn't hold the lock */
1640         oldts = 0;
1641         ts = afs_SearchServer(aport, uuidp, locktype, &oldts,
1642                               addr_uniquifier);
1643         if (ts) {
1644             ReleaseWriteLock(&afs_xserver);
1645             ReleaseWriteLock(&afs_xvcb);
1646             return ts;
1647         }
1648     } else {
1649         UpgradeSToWLock(&afs_xserver, 36);
1650     }
1651     ObtainWriteLock(&afs_xsrvAddr, 116);
1652     srvcount = afs_totalServers;
1653
1654     /* Reuse/allocate a new server structure */
1655     if (oldts) {
1656         newts = oldts;
1657     } else {
1658         newts = afs_osi_Alloc(sizeof(struct server));
1659         if (!newts)
1660             panic("malloc of server struct");
1661         afs_totalServers++;
1662         memset(newts, 0, sizeof(struct server));
1663
1664         /* Add the server struct to the afs_servers[] hash chain */
1665         srvhash =
1666             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1667         newts->next = afs_servers[srvhash];
1668         afs_servers[srvhash] = newts;
1669     }
1670
1671     /* Initialize the server structure */
1672     if (uuidp) {                /* Multihomed */
1673         newts->sr_uuid = *uuidp;
1674         newts->sr_addr_uniquifier = addr_uniquifier;
1675         newts->flags |= SRVR_MULTIHOMED;
1676     }
1677     if (acell)
1678         /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
1679         newts->cell = afs_GetCellStale(acell, 0);
1680
1681     /* For each IP address we are registering */
1682     for (k = 0; k < nservers; k++) {
1683         iphash = SHash(aserverp[k]);
1684
1685         /* Check if the srvAddr structure already exists. If so, remove
1686          * it from its server structure and add it to the new one.
1687          */
1688         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1689             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1690                 break;
1691         }
1692         if (oldsa && (oldsa->server != newts)) {
1693             afs_RemoveSrvAddr(oldsa, tv);       /* Remove from its server struct */
1694             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1695             newts->addr = oldsa;
1696         }
1697
1698         /* Reuse/allocate a new srvAddr structure */
1699         if (oldsa) {
1700             newsa = oldsa;
1701         } else {
1702             newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1703             if (!newsa)
1704                 panic("malloc of srvAddr struct");
1705             afs_totalSrvAddrs++;
1706             memset(newsa, 0, sizeof(struct srvAddr));
1707
1708             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1709             newsa->next_bkt = afs_srvAddrs[iphash];
1710             afs_srvAddrs[iphash] = newsa;
1711
1712             /* Hang off of the server structure  */
1713             newsa->next_sa = newts->addr;
1714             newts->addr = newsa;
1715
1716             /* Initialize the srvAddr Structure */
1717             newsa->sa_ip = aserverp[k];
1718             newsa->sa_portal = aport;
1719         }
1720
1721         /* Update the srvAddr Structure */
1722         newsa->server = newts;
1723         if (newts->flags & SRVR_ISDOWN)
1724             newsa->sa_flags |= SRVADDR_ISDOWN;
1725         if (uuidp)
1726             newsa->sa_flags |= SRVADDR_MH;
1727         else
1728             newsa->sa_flags &= ~SRVADDR_MH;
1729
1730         /* Compute preference values and resort */
1731         if (!newsa->sa_iprank) {
1732             afs_SetServerPrefs(newsa);  /* new server rank */
1733         }
1734     }
1735     afs_SortOneServer(newts);   /* Sort by rank */
1736
1737     /* If we reused the server struct, remove any of its srvAddr
1738      * structs that will no longer be associated with this server.
1739      */
1740     if (oldts) {                /* reused the server struct */
1741         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1742             nextsa = orphsa->next_sa;
1743             for (k = 0; k < nservers; k++) {
1744                 if (orphsa->sa_ip == aserverp[k])
1745                     break;      /* belongs */
1746             }
1747             if (k < nservers)
1748                 continue;       /* belongs */
1749
1750             /* Have a srvAddr struct. Now get a server struct (if not already) */
1751             if (!orphts) {
1752                 orphts = afs_osi_Alloc(sizeof(struct server));
1753                 if (!orphts)
1754                     panic("malloc of lo server struct");
1755                 memset(orphts, 0, sizeof(struct server));
1756                 afs_totalServers++;
1757
1758                 /* Add the orphaned server to the afs_servers[] hash chain.
1759                  * Its iphash does not matter since we never look up the server
1760                  * in the afs_servers table by its ip address (only by uuid -
1761                  * which this has none).
1762                  */
1763                 iphash = SHash(aserverp[k]);
1764                 orphts->next = afs_servers[iphash];
1765                 afs_servers[iphash] = orphts;
1766
1767                 if (acell)
1768                     /* Use the afs_GetCellStale variant to avoid afs_GetServer recursion. */
1769                     orphts->cell = afs_GetCellStale(acell, 0);
1770             }
1771
1772             /* Hang the srvAddr struct off of the server structure. The server
1773              * may have multiple srvAddrs, but it won't be marked multihomed.
1774              */
1775             afs_RemoveSrvAddr(orphsa, tv);      /* remove */
1776             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1777             orphts->addr = orphsa;
1778             orphsa->server = orphts;
1779             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1780             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1781         }
1782     }
1783     /* We can't need this below, and won't reacquire */
1784     ReleaseWriteLock(&afs_xvcb);
1785
1786     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1787     if (srvcount) {
1788         struct afs_stats_SrvUpDownInfo *upDownP;
1789         /* With the introduction of this new record, we need to adjust the
1790          * proper individual & global server up/down info.
1791          */
1792         upDownP = GetUpDownStats(newts);
1793         upDownP->numTtlRecords += srvcount;
1794         afs_stats_cmperf.srvRecords += srvcount;
1795         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1796             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1797     }
1798     /* We can't need this below, and won't reacquire */
1799     ReleaseWriteLock(&afs_xvcb);
1800
1801     ReleaseWriteLock(&afs_xsrvAddr);
1802
1803     if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1804         afs_GetCapabilities(newts);
1805
1806     ReleaseWriteLock(&afs_xserver);
1807     return (newts);
1808 }                               /* afs_GetServer */
1809
1810 void
1811 afs_ActivateServer(struct srvAddr *sap)
1812 {
1813     osi_timeval_t currTime;     /*Filled with current time */
1814     osi_timeval_t *currTimeP;   /*Ptr to above */
1815     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1816     struct server *aserver = sap->server;
1817
1818     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1819         /*
1820          * This server record has not yet been activated.  Go for it,
1821          * recording its ``birth''.
1822          */
1823         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1824         currTimeP = &currTime;
1825         osi_GetuTime(currTimeP);
1826         aserver->activationTime = currTime.tv_sec;
1827         upDownP = GetUpDownStats(aserver);
1828         if (aserver->flags & SRVR_ISDOWN) {
1829             upDownP->numDownRecords++;
1830         } else {
1831             upDownP->numUpRecords++;
1832             upDownP->numRecordsNeverDown++;
1833         }
1834     }
1835 }
1836
1837 void
1838 afs_RemoveAllConns(void)
1839 {
1840     int i;
1841     struct server *ts, *nts;
1842     struct srvAddr *sa;
1843
1844     ObtainReadLock(&afs_xserver);
1845     ObtainWriteLock(&afs_xconn, 1001);
1846
1847     /*printf("Destroying connections ... ");*/
1848     for (i = 0; i < NSERVERS; i++) {
1849         for (ts = afs_servers[i]; ts; ts = nts) {
1850             nts = ts->next;
1851             for (sa = ts->addr; sa; sa = sa->next_sa) {
1852                 if (sa->conns) {
1853                     afs_ReleaseConns(sa->conns);
1854                     sa->conns = NULL;
1855                     sa->natping = NULL;
1856                 }
1857             }
1858         }
1859     }
1860     /*printf("done\n");*/
1861
1862     ReleaseWriteLock(&afs_xconn);
1863     ReleaseReadLock(&afs_xserver);
1864
1865 }
1866
1867 void
1868 afs_MarkAllServersUp(void)
1869 {
1870     int i;
1871     struct server *ts;
1872     struct srvAddr *sa;
1873
1874     ObtainWriteLock(&afs_xserver, 721);
1875     ObtainWriteLock(&afs_xsrvAddr, 722);
1876     for (i = 0; i< NSERVERS; i++) {
1877         for (ts = afs_servers[i]; ts; ts = ts->next) {
1878             for (sa = ts->addr; sa; sa = sa->next_sa) {
1879                 afs_MarkServerUpOrDown(sa, 0);
1880             }
1881         }
1882     }
1883     ReleaseWriteLock(&afs_xsrvAddr);
1884     ReleaseWriteLock(&afs_xserver);
1885 }