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