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