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