Fix formatting issues in src/afs
[openafs.git] / src / afs / afs_server.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Implements:
12  * afs_MarkServerUpOrDown
13  * afs_ServerDown
14  * afs_CountServers
15  * afs_CheckServers
16  * afs_FindServer
17  * afs_random
18  * afs_randomMod127
19  * afs_SortServers
20  * afsi_SetServerIPRank
21  * afs_GetServer
22  * afs_ActivateServer
23  * 
24  *
25  * Local:
26  * HaveCallBacksFrom
27  * CheckVLServer
28  * afs_SortOneServer
29  * afs_SetServerPrefs
30  * 
31  */
32 #include <afsconfig.h>
33 #include "afs/param.h"
34
35
36 #include "afs/stds.h"
37 #include "afs/sysincludes.h"    /* Standard vendor system headers */
38
39 #if !defined(UKERNEL)
40 #if !defined(AFS_LINUX20_ENV)
41 #include <net/if.h>
42 #endif
43 #include <netinet/in.h>
44
45 #ifdef AFS_SGI62_ENV
46 #include "h/hashing.h"
47 #endif
48 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
49 #include <netinet/in_var.h>
50 #endif /* AFS_HPUX110_ENV */
51 #ifdef AFS_DARWIN_ENV
52 #include <net/if_var.h>
53 #endif
54 #endif /* !defined(UKERNEL) */
55
56 #include "afsincludes.h"        /* Afs-based standard headers */
57 #include "afs/afs_stats.h"      /* afs statistics */
58 #include "rx/rx_multi.h"
59
60 #if     defined(AFS_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_DARWIN_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_DARWIN_ENV) && defined(USEIFADDR)
1178 #ifndef afs_min
1179 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1180 #endif
1181 void
1182 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1183 {
1184     struct sockaddr sout;
1185     struct sockaddr_in *sin;
1186     int t;
1187
1188     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1189     afs_uint32 serverAddr;
1190
1191     if (rx_ifaddr_address_family(ifa) != AF_INET)
1192         return;
1193     t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1194     if (t == 0) {
1195         sin = (struct sockaddr_in *)&sout;
1196         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1197     } else {
1198         myAddr = 0;
1199     }
1200     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1201     t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1202     if (t == 0) {
1203         sin = (struct sockaddr_in *)&sout;
1204         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1205     } else {
1206         subnetmask = 0;
1207     }
1208     t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1209     if (t == 0) {
1210         sin = (struct sockaddr_in *)&sout;
1211         myDstaddr = sin->sin_addr.s_addr;
1212     } else {
1213         myDstaddr = 0;
1214     }
1215
1216     if (IN_CLASSA(myAddr))
1217         netMask = IN_CLASSA_NET;
1218     else if (IN_CLASSB(myAddr))
1219         netMask = IN_CLASSB_NET;
1220     else if (IN_CLASSC(myAddr))
1221         netMask = IN_CLASSC_NET;
1222     else
1223         netMask = 0;
1224
1225     myNet = myAddr & netMask;
1226     mySubnet = myAddr & subnetmask;
1227
1228     if ((serverAddr & netMask) == myNet) {
1229         if ((serverAddr & subnetmask) == mySubnet) {
1230             if (serverAddr == myAddr) { /* same machine */
1231                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1232             } else {            /* same subnet */
1233                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1234             }
1235         } else {                /* same net */
1236             sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1237         }
1238     }
1239 #ifdef  IFF_POINTTOPOINT
1240     /* check for case #4 -- point-to-point link */
1241     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1242         && (myDstaddr == serverAddr)) {
1243         if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1244             t = MAXDEFRANK;
1245         else
1246             t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1247         if (sa->sa_iprank > t)
1248             sa->sa_iprank = t;
1249         }
1250 #endif /* IFF_POINTTOPOINT */
1251 }
1252 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1253 #endif /* else AFS_USERSPACE_IP_ADDR */
1254
1255 #ifdef AFS_SGI62_ENV
1256 static int
1257 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1258                    caddr_t arg2)
1259 {
1260     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1261     return 0;                   /* Never match, so we enumerate everyone */
1262 }
1263 #endif                          /* AFS_SGI62_ENV */
1264 static int
1265 afs_SetServerPrefs(struct srvAddr *sa)
1266 {
1267 #if     defined(AFS_USERSPACE_IP_ADDR)
1268     int i;
1269
1270       sa->sa_iprank = LO;
1271     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1272         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1273                              afs_cb_interface.subnetmask[i]);
1274     }
1275 #else                           /* AFS_USERSPACE_IP_ADDR */
1276 #if     defined(AFS_SUN5_ENV)
1277 #ifdef AFS_SUN510_ENV
1278     int i = 0;
1279 #else
1280     extern struct ill_s *ill_g_headp;
1281     long *addr = (long *)ill_g_headp;
1282     ill_t *ill;
1283     ipif_t *ipif;
1284 #endif
1285     int subnet, subnetmask, net, netmask;
1286
1287     if (sa)
1288           sa->sa_iprank = 0;
1289 #ifdef AFS_SUN510_ENV
1290     rw_enter(&afsifinfo_lock, RW_READER);
1291
1292     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1293
1294         if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1295             netmask = IN_CLASSA_NET;
1296         } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1297             netmask = IN_CLASSB_NET;
1298         } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1299             netmask = IN_CLASSC_NET;
1300         } else {
1301             netmask = 0;
1302         }
1303         net = afsifinfo[i].ipaddr & netmask;
1304
1305 #ifdef notdef
1306         if (!s) {
1307             if (afsifinfo[i].ipaddr != 0x7f000001) {    /* ignore loopback */
1308                 *cnt += 1;
1309                 if (*cnt > 16)
1310                     return;
1311                 *addrp++ = afsifinfo[i].ipaddr;
1312             }
1313         } else
1314 #endif /* notdef */
1315         {
1316             /* XXXXXX Do the individual ip ranking below XXXXX */
1317             if ((sa->sa_ip & netmask) == net) {
1318                 if ((sa->sa_ip & subnetmask) == subnet) {
1319                     if (afsifinfo[i].ipaddr == sa->sa_ip) {   /* ie, ME!  */
1320                         sa->sa_iprank = TOPR;
1321                     } else {
1322                         sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1323                     }
1324                 } else {
1325                     sa->sa_iprank = MED + afsifinfo[i].metric;    /* case #3 */
1326                 }
1327             } else {
1328                     sa->sa_iprank = LO + afsifinfo[i].metric;     /* case #4 */
1329             }
1330             /* check for case #5 -- point-to-point link */
1331             if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1332                 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1333
1334                     if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1335                         sa->sa_iprank = MAXDEFRANK;
1336                     else
1337                         sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1338             }
1339         }
1340     }
1341     
1342     rw_exit(&afsifinfo_lock);
1343 #else
1344     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1345          ill = ill->ill_next) {
1346 #ifdef AFS_SUN58_ENV
1347         /* Make sure this is an IPv4 ILL */
1348         if (ill->ill_isv6)
1349             continue;
1350 #endif
1351         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1352             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1353             subnetmask = ipif->ipif_net_mask;
1354             /*
1355              * Generate the local net using the local address and 
1356              * whate we know about Class A, B and C networks.
1357              */
1358             if (IN_CLASSA(ipif->ipif_local_addr)) {
1359                 netmask = IN_CLASSA_NET;
1360             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1361                 netmask = IN_CLASSB_NET;
1362             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1363                 netmask = IN_CLASSC_NET;
1364             } else {
1365                 netmask = 0;
1366             }
1367             net = ipif->ipif_local_addr & netmask;
1368 #ifdef notdef
1369             if (!s) {
1370                 if (ipif->ipif_local_addr != 0x7f000001) {      /* ignore loopback */
1371                     *cnt += 1;
1372                     if (*cnt > 16)
1373                         return;
1374                     *addrp++ = ipif->ipif_local_addr;
1375                 }
1376             } else
1377 #endif /* notdef */
1378             {
1379                 /* XXXXXX Do the individual ip ranking below XXXXX */
1380                 if ((sa->sa_ip & netmask) == net) {
1381                     if ((sa->sa_ip & subnetmask) == subnet) {
1382                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1383                             sa->sa_iprank = TOPR;
1384                         } else {
1385                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1386                         }
1387                     } else {
1388                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1389                     }
1390                 } else {
1391                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1392                 }
1393                 /* check for case #5 -- point-to-point link */
1394                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1395                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1396
1397                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1398                         sa->sa_iprank = MAXDEFRANK;
1399                     else
1400                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1401                 }
1402             }
1403         }
1404     }
1405 #endif /* AFS_SUN510_ENV */
1406 #else
1407 #ifndef USEIFADDR
1408     rx_ifnet_t ifn = NULL;
1409     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1410     struct sockaddr_in *sin;
1411
1412     if (!sa) {
1413 #ifdef notdef                   /* clean up, remove this */
1414         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1415             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1416                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1417                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1418                     *cnt += 1;
1419                     if (*cnt > 16)
1420                         return;
1421                     *addrp++ =
1422                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1423                         s_addr;
1424                 }
1425         }}
1426 #endif                          /* notdef */
1427         return;
1428     }
1429     sa->sa_iprank = 0;
1430 #ifdef  ADAPT_MTU
1431     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1432 #endif
1433     if (ifn) {                  /* local, more or less */
1434 #ifdef IFF_LOOPBACK
1435         if (ifn->if_flags & IFF_LOOPBACK) {
1436             sa->sa_iprank = TOPR;
1437             goto end;
1438         }
1439 #endif /* IFF_LOOPBACK */
1440         sin = (struct sockaddr_in *)IA_SIN(ifad);
1441         if (SA2ULONG(sin) == sa->sa_ip) {
1442             sa->sa_iprank = TOPR;
1443             goto end;
1444         }
1445 #ifdef IFF_BROADCAST
1446         if (ifn->if_flags & IFF_BROADCAST) {
1447             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1448                 sa->sa_iprank = HI;
1449                 goto end;
1450             }
1451         }
1452 #endif /* IFF_BROADCAST */
1453 #ifdef IFF_POINTOPOINT
1454         if (ifn->if_flags & IFF_POINTOPOINT) {
1455             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1456                 if (ifn->if_metric > 4) {
1457                     sa->sa_iprank = LO;
1458                     goto end;
1459                 } else
1460                     sa->sa_iprank = ifn->if_metric;
1461             }
1462         }
1463 #endif /* IFF_POINTOPOINT */
1464         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1465     }
1466 #else                           /* USEIFADDR */
1467
1468     if (sa)
1469         sa->sa_iprank = LO;
1470 #ifdef AFS_SGI62_ENV
1471     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1472                     (caddr_t) sa, NULL);
1473 #elif defined(AFS_DARWIN80_ENV)
1474     {
1475         errno_t t;
1476         unsigned int count;
1477         int cnt=0, m, j;
1478         rx_ifaddr_t *ifads;
1479         rx_ifnet_t *ifns;
1480
1481         if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1482             for (m = 0; m < count; m++) {
1483                 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1484                     for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1485                         afsi_SetServerIPRank(sa, ifads[j]);
1486                         cnt++;
1487                     }
1488                     ifnet_free_address_list(ifads);
1489                 }
1490             }
1491             ifnet_list_free(ifns);
1492         }
1493     }
1494 #elif defined(AFS_DARWIN_ENV)
1495     {
1496         rx_ifnet_t ifn;
1497         rx_ifaddr_t ifa;
1498           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1499             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1500                 afsi_SetServerIPRank(sa, ifa);
1501     }}}
1502 #elif defined(AFS_FBSD_ENV)
1503     {
1504         struct in_ifaddr *ifa;
1505           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1506             afsi_SetServerIPRank(sa, ifa);
1507     }}
1508 #elif defined(AFS_OBSD_ENV)
1509     {
1510         extern struct in_ifaddrhead in_ifaddr;
1511         struct in_ifaddr *ifa;
1512         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1513             afsi_SetServerIPRank(sa, ifa);
1514     }
1515 #else
1516     {
1517         struct in_ifaddr *ifa;
1518         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1519             afsi_SetServerIPRank(sa, ifa);
1520     }}
1521 #endif
1522 #endif                          /* USEIFADDR */
1523 #ifndef USEIFADDR
1524     end:
1525 #endif
1526 #endif                          /* AFS_SUN5_ENV */
1527 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1528     if (sa)
1529           sa->sa_iprank += afs_randomMod15();
1530
1531     return 0;
1532 }                               /* afs_SetServerPrefs */
1533
1534 #undef TOPR
1535 #undef HI
1536 #undef MED
1537 #undef LO
1538 #undef PPWEIGHT
1539
1540 /* afs_FlushServer()
1541  * The addresses on this server struct has changed in some way and will
1542  * clean up all other structures that may reference it.
1543  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1544  */
1545 void
1546 afs_FlushServer(struct server *srvp)
1547 {
1548     afs_int32 i;
1549     struct server *ts, **pts;
1550
1551     /* Find any volumes residing on this server and flush their state */
1552       afs_ResetVolumes(srvp);
1553
1554     /* Flush all callbacks in the all vcaches for this specific server */
1555       afs_FlushServerCBs(srvp);
1556
1557     /* Remove all the callbacks structs */
1558     if (srvp->cbrs) {
1559         struct afs_cbr *cb, *cbnext;
1560
1561           ObtainWriteLock(&afs_xvcb, 300);
1562         for (cb = srvp->cbrs; cb; cb = cbnext) {
1563             cbnext = cb->next;
1564             afs_FreeCBR(cb);
1565         } srvp->cbrs = (struct afs_cbr *)0;
1566         ReleaseWriteLock(&afs_xvcb);
1567     }
1568
1569     /* If no more srvAddr structs hanging off of this server struct,
1570      * then clean it up.
1571      */
1572     if (!srvp->addr) {
1573         /* Remove the server structure from the cell list - if there */
1574         afs_RemoveCellEntry(srvp);
1575
1576         /* Remove from the afs_servers hash chain */
1577         for (i = 0; i < NSERVERS; i++) {
1578             for (pts = &(afs_servers[i]), ts = *pts; ts;
1579                  pts = &(ts->next), ts = *pts) {
1580                 if (ts == srvp)
1581                     break;
1582             }
1583             if (ts)
1584                 break;
1585         }
1586         if (ts) {
1587             *pts = ts->next;    /* Found it. Remove it */
1588             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1589             afs_totalServers--;
1590         }
1591     }
1592 }
1593
1594 /* afs_RemoveSrvAddr()
1595  * This removes a SrvAddr structure from its server structure.
1596  * The srvAddr struct is not free'd because it connections may still
1597  * be open to it. It is up to the calling process to make sure it
1598  * remains connected to a server struct.
1599  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1600  *    It is not removed from the afs_srvAddrs hash chain.
1601  */
1602 void
1603 afs_RemoveSrvAddr(struct srvAddr *sap)
1604 {
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 *
1633 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1634               u_short aport, afs_int32 locktype, afsUUID * uuidp,
1635               afs_int32 addr_uniquifier)
1636 {
1637     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1638     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1639     u_short fsport;
1640     afs_int32 iphash, k, srvcount = 0;
1641     unsigned int srvhash;
1642
1643     AFS_STATCNT(afs_GetServer);
1644
1645     ObtainSharedLock(&afs_xserver, 13);
1646
1647     /* Check if the server struct exists and is up to date */
1648     if (!uuidp) {
1649         if (nservers != 1)
1650             panic("afs_GetServer: incorect count of servers");
1651         ObtainReadLock(&afs_xsrvAddr);
1652         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1653         ReleaseReadLock(&afs_xsrvAddr);
1654         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1655             /* Found a server struct that is not multihomed and has the
1656              * IP address associated with it. A correct match.
1657              */
1658             ReleaseSharedLock(&afs_xserver);
1659             return (ts);
1660         }
1661     } else {
1662         if (nservers <= 0)
1663             panic("afs_GetServer: incorrect count of servers");
1664         ts = afs_FindServer(0, aport, uuidp, locktype);
1665         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1666             /* Found a server struct that is multihomed and same
1667              * uniqufier (same IP addrs). The above if statement is the
1668              * same as in InstallUVolumeEntry().
1669              */
1670             ReleaseSharedLock(&afs_xserver);
1671             return ts;
1672         }
1673         if (ts)
1674             oldts = ts;         /* Will reuse if same uuid */
1675     }
1676
1677     UpgradeSToWLock(&afs_xserver, 36);
1678     ObtainWriteLock(&afs_xsrvAddr, 116);
1679
1680     srvcount = afs_totalServers;
1681
1682     /* Reuse/allocate a new server structure */
1683     if (oldts) {
1684         newts = oldts;
1685     } else {
1686         newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1687         if (!newts)
1688             panic("malloc of server struct");
1689         afs_totalServers++;
1690         memset(newts, 0, sizeof(struct server));
1691
1692         /* Add the server struct to the afs_servers[] hash chain */
1693         srvhash =
1694             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1695         newts->next = afs_servers[srvhash];
1696         afs_servers[srvhash] = newts;
1697     }
1698
1699     /* Initialize the server structure */
1700     if (uuidp) {                /* Multihomed */
1701         newts->sr_uuid = *uuidp;
1702         newts->sr_addr_uniquifier = addr_uniquifier;
1703         newts->flags |= SRVR_MULTIHOMED;
1704     }
1705     if (acell)
1706         newts->cell = afs_GetCell(acell, 0);
1707
1708     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1709
1710     /* For each IP address we are registering */
1711     for (k = 0; k < nservers; k++) {
1712         iphash = SHash(aserverp[k]);
1713
1714         /* Check if the srvAddr structure already exists. If so, remove
1715          * it from its server structure and add it to the new one.
1716          */
1717         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1718             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1719                 break;
1720         }
1721         if (oldsa && (oldsa->server != newts)) {
1722             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1723             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1724             newts->addr = oldsa;
1725         }
1726
1727         /* Reuse/allocate a new srvAddr structure */
1728         if (oldsa) {
1729             newsa = oldsa;
1730         } else {
1731             newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1732             if (!newsa)
1733                 panic("malloc of srvAddr struct");
1734             afs_totalSrvAddrs++;
1735             memset(newsa, 0, sizeof(struct srvAddr));
1736
1737             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1738             newsa->next_bkt = afs_srvAddrs[iphash];
1739             afs_srvAddrs[iphash] = newsa;
1740
1741             /* Hang off of the server structure  */
1742             newsa->next_sa = newts->addr;
1743             newts->addr = newsa;
1744
1745             /* Initialize the srvAddr Structure */
1746             newsa->sa_ip = aserverp[k];
1747             newsa->sa_portal = aport;
1748         }
1749
1750         /* Update the srvAddr Structure */
1751         newsa->server = newts;
1752         if (newts->flags & SRVR_ISDOWN)
1753             newsa->sa_flags |= SRVADDR_ISDOWN;
1754         if (uuidp)
1755             newsa->sa_flags |= SRVADDR_MH;
1756         else
1757             newsa->sa_flags &= ~SRVADDR_MH;
1758
1759         /* Compute preference values and resort */
1760         if (!newsa->sa_iprank) {
1761             afs_SetServerPrefs(newsa);  /* new server rank */
1762         }
1763     }
1764     afs_SortOneServer(newts);   /* Sort by rank */
1765
1766     /* If we reused the server struct, remove any of its srvAddr
1767      * structs that will no longer be associated with this server.
1768      */
1769     if (oldts) {                /* reused the server struct */
1770         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1771             nextsa = orphsa->next_sa;
1772             for (k = 0; k < nservers; k++) {
1773                 if (orphsa->sa_ip == aserverp[k])
1774                     break;      /* belongs */
1775             }
1776             if (k < nservers)
1777                 continue;       /* belongs */
1778
1779             /* Have a srvAddr struct. Now get a server struct (if not already) */
1780             if (!orphts) {
1781                 orphts =
1782                     (struct server *)afs_osi_Alloc(sizeof(struct server));
1783                 if (!orphts)
1784                     panic("malloc of lo server struct");
1785                 memset(orphts, 0, sizeof(struct server));
1786                 afs_totalServers++;
1787
1788                 /* Add the orphaned server to the afs_servers[] hash chain.
1789                  * Its iphash does not matter since we never look up the server
1790                  * in the afs_servers table by its ip address (only by uuid - 
1791                  * which this has none).
1792                  */
1793                 iphash = SHash(aserverp[k]);
1794                 orphts->next = afs_servers[iphash];
1795                 afs_servers[iphash] = orphts;
1796
1797                 if (acell)
1798                     orphts->cell = afs_GetCell(acell, 0);
1799             }
1800
1801             /* Hang the srvAddr struct off of the server structure. The server
1802              * may have multiple srvAddrs, but it won't be marked multihomed.
1803              */
1804             afs_RemoveSrvAddr(orphsa);  /* remove */
1805             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1806             orphts->addr = orphsa;
1807             orphsa->server = orphts;
1808             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1809             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1810         }
1811     }
1812
1813     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1814     if (srvcount) {
1815         struct afs_stats_SrvUpDownInfo *upDownP;
1816         /* With the introduction of this new record, we need to adjust the
1817          * proper individual & global server up/down info.
1818          */
1819         upDownP = GetUpDownStats(newts);
1820         upDownP->numTtlRecords += srvcount;
1821         afs_stats_cmperf.srvRecords += srvcount;
1822         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1823             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1824     }
1825
1826     ReleaseWriteLock(&afs_xsrvAddr);
1827     ReleaseWriteLock(&afs_xserver);
1828     return (newts);
1829 }                               /* afs_GetServer */
1830
1831 void
1832 afs_ActivateServer(struct srvAddr *sap)
1833 {
1834     osi_timeval_t currTime;     /*Filled with current time */
1835     osi_timeval_t *currTimeP;   /*Ptr to above */
1836     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1837     struct server *aserver = sap->server;
1838
1839     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1840         /*
1841          * This server record has not yet been activated.  Go for it,
1842          * recording its ``birth''.
1843          */
1844         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1845         currTimeP = &currTime;
1846         osi_GetuTime(currTimeP);
1847         aserver->activationTime = currTime.tv_sec;
1848         upDownP = GetUpDownStats(aserver);
1849         if (aserver->flags & SRVR_ISDOWN) {
1850             upDownP->numDownRecords++;
1851         } else {
1852             upDownP->numUpRecords++;
1853             upDownP->numRecordsNeverDown++;
1854         }
1855     }
1856 }
1857
1858 void
1859 afs_RemoveAllConns(void)
1860 {
1861     int i;
1862     struct server *ts, *nts;
1863     struct srvAddr *sa;
1864     struct afs_conn *tc, *ntc;
1865
1866     ObtainReadLock(&afs_xserver);
1867     ObtainWriteLock(&afs_xconn, 1001);
1868     
1869     /*printf("Destroying connections ... ");*/
1870     for (i = 0; i < NSERVERS; i++) {
1871         for (ts = afs_servers[i]; ts; ts = nts) {
1872             nts = ts->next;
1873             for (sa = ts->addr; sa; sa = sa->next_sa) {
1874                 if (sa->conns) {
1875                     tc = sa->conns;
1876                     while (tc) {
1877                         ntc = tc->next;
1878                         AFS_GUNLOCK();
1879                         rx_DestroyConnection(tc->id);
1880                         AFS_GLOCK();
1881                         afs_osi_Free(tc, sizeof(struct afs_conn));
1882                         tc = ntc;
1883                     }
1884                     sa->conns = NULL;
1885                 }
1886             }
1887         }
1888     }
1889     /*printf("done\n");*/
1890
1891     ReleaseWriteLock(&afs_xconn);
1892     ReleaseReadLock(&afs_xserver);
1893     
1894 }
1895
1896 void
1897 afs_MarkAllServersUp(void)
1898 {
1899     int i;
1900     struct server *ts;
1901     struct srvAddr *sa;
1902
1903     ObtainWriteLock(&afs_xserver, 721);
1904     ObtainWriteLock(&afs_xsrvAddr, 722);
1905     for (i = 0; i< NSERVERS; i++) {
1906         for (ts = afs_servers[i]; ts; ts = ts->next) {
1907             for (sa = ts->addr; sa; sa = sa->next_sa) {
1908                 afs_MarkServerUpOrDown(sa, 0);
1909             }
1910         }
1911     }
1912     ReleaseWriteLock(&afs_xsrvAddr);
1913     ReleaseWriteLock(&afs_xserver);
1914 }