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