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