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