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