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