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