abstract rx if structure access
[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      rx_ifaddr_t ifa;
1185 {
1186     struct sockaddr sout;
1187     struct sockaddr_in *sin;
1188     int t;
1189
1190     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1191     afs_uint32 serverAddr;
1192
1193     if (rx_ifaddr_address_family(ifa) != AF_INET)
1194         return;
1195     t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1196     if (t == 0) {
1197         sin = (struct sockaddr_in *)&sout;
1198         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1199     } else {
1200         myAddr = 0;
1201     }
1202     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1203     t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1204     if (t == 0) {
1205         sin = (struct sockaddr_in *)&sout;
1206         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1207     } else {
1208         subnetmask = 0;
1209     }
1210     t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1211     if (t == 0) {
1212         sin = (struct sockaddr_in *)&sout;
1213         myDstaddr = sin->sin_addr.s_addr;
1214     } else {
1215         myDstaddr = 0;
1216     }
1217
1218     if (IN_CLASSA(myAddr))
1219         netMask = IN_CLASSA_NET;
1220     else if (IN_CLASSB(myAddr))
1221         netMask = IN_CLASSB_NET;
1222     else if (IN_CLASSC(myAddr))
1223         netMask = IN_CLASSC_NET;
1224     else
1225         netMask = 0;
1226
1227     myNet = myAddr & netMask;
1228     mySubnet = myAddr & subnetmask;
1229
1230     if ((serverAddr & netMask) == myNet) {
1231         if ((serverAddr & subnetmask) == mySubnet) {
1232             if (serverAddr == myAddr) { /* same machine */
1233                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1234             } else {            /* same subnet */
1235                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1236             }
1237         } else {                /* same net */
1238             sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1239         }
1240     }
1241 #ifdef  IFF_POINTTOPOINT
1242     /* check for case #4 -- point-to-point link */
1243     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1244         && (myDstaddr == serverAddr)) {
1245         if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1246             t = MAXDEFRANK;
1247         else
1248             t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1249         if (sa->sa_iprank > t)
1250             sa->sa_iprank = t;
1251         }
1252 #endif /* IFF_POINTTOPOINT */
1253 }
1254 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1255 #endif /* else AFS_USERSPACE_IP_ADDR */
1256
1257 #ifdef AFS_SGI62_ENV
1258 static int
1259
1260   afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1261                      caddr_t arg2) {
1262     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1263     return 0;                   /* Never match, so we enumerate everyone */
1264 }
1265 #endif                          /* AFS_SGI62_ENV */
1266 static int afs_SetServerPrefs(struct srvAddr *sa) {
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_DARWIN60_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_DARWIN_ENV) || 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 afs_FlushServer(struct server *srvp) {
1546     afs_int32 i;
1547     struct server *ts, **pts;
1548
1549     /* Find any volumes residing on this server and flush their state */
1550       afs_ResetVolumes(srvp);
1551
1552     /* Flush all callbacks in the all vcaches for this specific server */
1553       afs_FlushServerCBs(srvp);
1554
1555     /* Remove all the callbacks structs */
1556     if (srvp->cbrs) {
1557         struct afs_cbr *cb, *cbnext;
1558
1559           ObtainWriteLock(&afs_xvcb, 300);
1560         for (cb = srvp->cbrs; cb; cb = cbnext) {
1561             cbnext = cb->next;
1562             afs_FreeCBR(cb);
1563         } srvp->cbrs = (struct afs_cbr *)0;
1564         ReleaseWriteLock(&afs_xvcb);
1565     }
1566
1567     /* If no more srvAddr structs hanging off of this server struct,
1568      * then clean it up.
1569      */
1570     if (!srvp->addr) {
1571         /* Remove the server structure from the cell list - if there */
1572         afs_RemoveCellEntry(srvp);
1573
1574         /* Remove from the afs_servers hash chain */
1575         for (i = 0; i < NSERVERS; i++) {
1576             for (pts = &(afs_servers[i]), ts = *pts; ts;
1577                  pts = &(ts->next), ts = *pts) {
1578                 if (ts == srvp)
1579                     break;
1580             }
1581             if (ts)
1582                 break;
1583         }
1584         if (ts) {
1585             *pts = ts->next;    /* Found it. Remove it */
1586             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1587             afs_totalServers--;
1588         }
1589     }
1590 }
1591
1592 /* afs_RemoveSrvAddr()
1593  * This removes a SrvAddr structure from its server structure.
1594  * The srvAddr struct is not free'd because it connections may still
1595  * be open to it. It is up to the calling process to make sure it
1596  * remains connected to a server struct.
1597  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1598  *    It is not removed from the afs_srvAddrs hash chain.
1599  */
1600 void afs_RemoveSrvAddr(struct srvAddr *sap) {
1601     struct srvAddr **psa, *sa;
1602     struct server *srv;
1603
1604     if (!sap)
1605           return;
1606       srv = sap->server;
1607
1608     /* Find the srvAddr in the server's list and remove it */
1609     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1610         if (sa == sap)
1611             break;
1612     } if (sa) {
1613         *psa = sa->next_sa;
1614         sa->next_sa = 0;
1615         sa->server = 0;
1616
1617         /* Flush the server struct since it's IP address has changed */
1618         afs_FlushServer(srv);
1619     }
1620 }
1621
1622 /* afs_GetServer()
1623  * Return an updated and properly initialized server structure
1624  * corresponding to the server ID, cell, and port specified.
1625  * If one does not exist, then one will be created.
1626  * aserver and aport must be in NET byte order.
1627  */
1628 struct server *afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers,
1629                              afs_int32 acell, u_short aport,
1630                              afs_int32 locktype, afsUUID * uuidp,
1631                              afs_int32 addr_uniquifier) {
1632     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1633     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1634     u_short fsport;
1635     afs_int32 iphash, k, srvcount = 0;
1636     unsigned int srvhash;
1637
1638     AFS_STATCNT(afs_GetServer);
1639
1640     ObtainSharedLock(&afs_xserver, 13);
1641
1642     /* Check if the server struct exists and is up to date */
1643     if (!uuidp) {
1644         if (nservers != 1)
1645             panic("afs_GetServer: incorect count of servers");
1646         ObtainReadLock(&afs_xsrvAddr);
1647         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1648         ReleaseReadLock(&afs_xsrvAddr);
1649         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1650             /* Found a server struct that is not multihomed and has the
1651              * IP address associated with it. A correct match.
1652              */
1653             ReleaseSharedLock(&afs_xserver);
1654             return (ts);
1655         }
1656     } else {
1657         if (nservers <= 0)
1658             panic("afs_GetServer: incorrect count of servers");
1659         ts = afs_FindServer(0, aport, uuidp, locktype);
1660         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1661             /* Found a server struct that is multihomed and same
1662              * uniqufier (same IP addrs). The above if statement is the
1663              * same as in InstallUVolumeEntry().
1664              */
1665             ReleaseSharedLock(&afs_xserver);
1666             return ts;
1667         }
1668         if (ts)
1669             oldts = ts;         /* Will reuse if same uuid */
1670     }
1671
1672     UpgradeSToWLock(&afs_xserver, 36);
1673     ObtainWriteLock(&afs_xsrvAddr, 116);
1674
1675     srvcount = afs_totalServers;
1676
1677     /* Reuse/allocate a new server structure */
1678     if (oldts) {
1679         newts = oldts;
1680     } else {
1681         newts = (struct server *)afs_osi_Alloc(sizeof(struct server));
1682         if (!newts)
1683             panic("malloc of server struct");
1684         afs_totalServers++;
1685         memset(newts, 0, sizeof(struct server));
1686
1687         /* Add the server struct to the afs_servers[] hash chain */
1688         srvhash =
1689             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1690         newts->next = afs_servers[srvhash];
1691         afs_servers[srvhash] = newts;
1692     }
1693
1694     /* Initialize the server structure */
1695     if (uuidp) {                /* Multihomed */
1696         newts->sr_uuid = *uuidp;
1697         newts->sr_addr_uniquifier = addr_uniquifier;
1698         newts->flags |= SRVR_MULTIHOMED;
1699     }
1700     if (acell)
1701         newts->cell = afs_GetCell(acell, 0);
1702
1703     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1704
1705     /* For each IP address we are registering */
1706     for (k = 0; k < nservers; k++) {
1707         iphash = SHash(aserverp[k]);
1708
1709         /* Check if the srvAddr structure already exists. If so, remove
1710          * it from its server structure and add it to the new one.
1711          */
1712         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1713             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1714                 break;
1715         }
1716         if (oldsa && (oldsa->server != newts)) {
1717             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1718             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1719             newts->addr = oldsa;
1720         }
1721
1722         /* Reuse/allocate a new srvAddr structure */
1723         if (oldsa) {
1724             newsa = oldsa;
1725         } else {
1726             newsa = (struct srvAddr *)afs_osi_Alloc(sizeof(struct srvAddr));
1727             if (!newsa)
1728                 panic("malloc of srvAddr struct");
1729             afs_totalSrvAddrs++;
1730             memset(newsa, 0, sizeof(struct srvAddr));
1731
1732             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1733             newsa->next_bkt = afs_srvAddrs[iphash];
1734             afs_srvAddrs[iphash] = newsa;
1735
1736             /* Hang off of the server structure  */
1737             newsa->next_sa = newts->addr;
1738             newts->addr = newsa;
1739
1740             /* Initialize the srvAddr Structure */
1741             newsa->sa_ip = aserverp[k];
1742             newsa->sa_portal = aport;
1743         }
1744
1745         /* Update the srvAddr Structure */
1746         newsa->server = newts;
1747         if (newts->flags & SRVR_ISDOWN)
1748             newsa->sa_flags |= SRVADDR_ISDOWN;
1749         if (uuidp)
1750             newsa->sa_flags |= SRVADDR_MH;
1751         else
1752             newsa->sa_flags &= ~SRVADDR_MH;
1753
1754         /* Compute preference values and resort */
1755         if (!newsa->sa_iprank) {
1756             afs_SetServerPrefs(newsa);  /* new server rank */
1757         }
1758     }
1759     afs_SortOneServer(newts);   /* Sort by rank */
1760
1761     /* If we reused the server struct, remove any of its srvAddr
1762      * structs that will no longer be associated with this server.
1763      */
1764     if (oldts) {                /* reused the server struct */
1765         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1766             nextsa = orphsa->next_sa;
1767             for (k = 0; k < nservers; k++) {
1768                 if (orphsa->sa_ip == aserverp[k])
1769                     break;      /* belongs */
1770             }
1771             if (k < nservers)
1772                 continue;       /* belongs */
1773
1774             /* Have a srvAddr struct. Now get a server struct (if not already) */
1775             if (!orphts) {
1776                 orphts =
1777                     (struct server *)afs_osi_Alloc(sizeof(struct server));
1778                 if (!orphts)
1779                     panic("malloc of lo server struct");
1780                 memset(orphts, 0, sizeof(struct server));
1781                 afs_totalServers++;
1782
1783                 /* Add the orphaned server to the afs_servers[] hash chain.
1784                  * Its iphash does not matter since we never look up the server
1785                  * in the afs_servers table by its ip address (only by uuid - 
1786                  * which this has none).
1787                  */
1788                 iphash = SHash(aserverp[k]);
1789                 orphts->next = afs_servers[iphash];
1790                 afs_servers[iphash] = orphts;
1791
1792                 if (acell)
1793                     orphts->cell = afs_GetCell(acell, 0);
1794             }
1795
1796             /* Hang the srvAddr struct off of the server structure. The server
1797              * may have multiple srvAddrs, but it won't be marked multihomed.
1798              */
1799             afs_RemoveSrvAddr(orphsa);  /* remove */
1800             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1801             orphts->addr = orphsa;
1802             orphsa->server = orphts;
1803             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1804             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1805         }
1806     }
1807
1808     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1809     if (srvcount) {
1810         struct afs_stats_SrvUpDownInfo *upDownP;
1811         /* With the introduction of this new record, we need to adjust the
1812          * proper individual & global server up/down info.
1813          */
1814         upDownP = GetUpDownStats(newts);
1815         upDownP->numTtlRecords += srvcount;
1816         afs_stats_cmperf.srvRecords += srvcount;
1817         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1818             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1819     }
1820
1821     ReleaseWriteLock(&afs_xsrvAddr);
1822     ReleaseWriteLock(&afs_xserver);
1823     return (newts);
1824 }                               /* afs_GetServer */
1825
1826 void afs_ActivateServer(struct srvAddr *sap) {
1827     osi_timeval_t currTime;     /*Filled with current time */
1828     osi_timeval_t *currTimeP;   /*Ptr to above */
1829     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1830     struct server *aserver = sap->server;
1831
1832     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1833         /*
1834          * This server record has not yet been activated.  Go for it,
1835          * recording its ``birth''.
1836          */
1837         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1838         currTimeP = &currTime;
1839         osi_GetuTime(currTimeP);
1840         aserver->activationTime = currTime.tv_sec;
1841         upDownP = GetUpDownStats(aserver);
1842         if (aserver->flags & SRVR_ISDOWN) {
1843             upDownP->numDownRecords++;
1844         } else {
1845             upDownP->numUpRecords++;
1846             upDownP->numRecordsNeverDown++;
1847         }
1848     }
1849 }
1850
1851 void afs_RemoveAllConns(void)
1852 {
1853     int i;
1854     struct server *ts, *nts;
1855     struct srvAddr *sa;
1856     struct afs_conn *tc, *ntc;
1857
1858     ObtainReadLock(&afs_xserver);
1859     ObtainWriteLock(&afs_xconn, 1001);
1860     
1861     /*printf("Destroying connections ... ");*/
1862     for (i = 0; i < NSERVERS; i++) {
1863         for (ts = afs_servers[i]; ts; ts = nts) {
1864             nts = ts->next;
1865             for (sa = ts->addr; sa; sa = sa->next_sa) {
1866                 if (sa->conns) {
1867                     tc = sa->conns;
1868                     while (tc) {
1869                         ntc = tc->next;
1870                         AFS_GUNLOCK();
1871                         rx_DestroyConnection(tc->id);
1872                         AFS_GLOCK();
1873                         afs_osi_Free(tc, sizeof(struct afs_conn));
1874                         tc = ntc;
1875                     }
1876                     sa->conns = NULL;
1877                 }
1878             }
1879         }
1880     }
1881     /*printf("done\n");*/
1882
1883     ReleaseWriteLock(&afs_xconn);
1884     ReleaseReadLock(&afs_xserver);
1885     
1886 }
1887
1888 void afs_MarkAllServersUp(void)
1889 {
1890     int i;
1891     struct server *ts;
1892     struct srvAddr *sa;
1893
1894     ObtainWriteLock(&afs_xserver, 721);
1895     ObtainWriteLock(&afs_xsrvAddr, 722);
1896     for (i = 0; i< NSERVERS; i++) {
1897         for (ts = afs_servers[i]; ts; ts = ts->next) {
1898             for (sa = ts->addr; sa; sa = sa->next_sa) {
1899                 afs_MarkServerUpOrDown(sa, 0);
1900             }
1901         }
1902     }
1903     ReleaseWriteLock(&afs_xsrvAddr);
1904     ReleaseWriteLock(&afs_xserver);
1905 }