Linux: Fix prototypes for afs_xsetgroups and sys_setgroupsp and friends
[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     struct server *a_serverP = sa->server;
134     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     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     afs_int32 now;
264     int i;
265     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(struct srvAddr *sa, struct vrequest *areq)
287 {
288     struct server *aserver = sa->server;
289     struct afs_conn *tc;
290     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     osi_Assert(addrs != NULL);
509     j = 0;
510     for (i = 0; i < NSERVERS; i++) {
511         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
512             if (j >= srvAddrCount)
513                 break;
514             addrs[j++] = sa;
515         }
516     }
517
518     ReleaseReadLock(&afs_xsrvAddr);
519     ReleaseReadLock(&afs_xserver);
520     for (i = 0; i < j; i++) {
521         sa = addrs[i];
522         ForceNewConnections(sa);
523     }
524 }
525
526 /* check down servers (if adown), or running servers (if !adown) */
527 void
528 afs_CheckServers(int adown, struct cell *acellp)
529 {
530     struct vrequest treq;
531     struct server *ts;
532     struct srvAddr *sa;
533     struct afs_conn *tc;
534     afs_int32 i, j;
535     afs_int32 code;
536     afs_int32 start, end = 0, delta;
537     osi_timeval_t tv;
538     struct unixuser *tu;
539     char tbuffer[CVBS];
540     int srvAddrCount;
541     struct srvAddr **addrs;
542     struct afs_conn **conns;
543     int nconns;
544     struct rx_connection **rxconns;
545     afs_int32 *conntimer, *deltas, *results;
546     Capabilities *caps = NULL;
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     osi_Assert(addrs != NULL);
576     j = 0;
577     for (i = 0; i < NSERVERS; i++) {
578         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
579             if (j >= srvAddrCount)
580                 break;
581             addrs[j++] = sa;
582         }
583     }
584
585     ReleaseReadLock(&afs_xsrvAddr);
586     ReleaseReadLock(&afs_xserver);
587
588     conns = afs_osi_Alloc(j * sizeof(struct afs_conn *));
589     osi_Assert(conns != NULL);
590     rxconns = afs_osi_Alloc(j * sizeof(struct rx_connection *));
591     osi_Assert(rxconns != NULL);
592     conntimer = afs_osi_Alloc(j * sizeof (afs_int32));
593     osi_Assert(conntimer != NULL);
594     deltas = afs_osi_Alloc(j * sizeof (afs_int32));
595     osi_Assert(deltas != NULL);
596     results = afs_osi_Alloc(j * sizeof (afs_int32));
597     osi_Assert(results != NULL);
598
599     caps = afs_osi_Alloc(j * sizeof (Capabilities));
600     osi_Assert(caps != NULL);
601     memset(caps, 0, j * sizeof(Capabilities));
602
603     for (i = 0; i < j; i++) {
604         deltas[i] = 0;
605         sa = addrs[i];
606         ts = sa->server;
607         if (!ts)
608             continue;
609
610         /* See if a cell to check was specified.  If it is spec'd and not
611          * this server's cell, just skip the server.
612          */
613         if (acellp && acellp != ts->cell)
614             continue;
615
616         if ((!adown && (sa->sa_flags & SRVADDR_ISDOWN))
617             || (adown && !(sa->sa_flags & SRVADDR_ISDOWN)))
618             continue;
619
620         /* check vlserver with special code */
621         if (sa->sa_portal == AFS_VLPORT) {
622             CheckVLServer(sa, &treq);
623             continue;
624         }
625
626         if (!ts->cell)          /* not really an active server, anyway, it must */
627             continue;           /* have just been added by setsprefs */
628
629         /* get a connection, even if host is down; bumps conn ref count */
630         tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
631         tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu,
632                           1 /*force */ , 1 /*create */ , SHARED_LOCK);
633         afs_PutUser(tu, SHARED_LOCK);
634         if (!tc)
635             continue;
636
637         if ((sa->sa_flags & SRVADDR_ISDOWN) || afs_HaveCallBacksFrom(sa->server)
638             || (tc->srvr->server == afs_setTimeHost)) {
639             conns[nconns]=tc;
640             rxconns[nconns]=tc->id;
641             if (sa->sa_flags & SRVADDR_ISDOWN) {
642                 rx_SetConnDeadTime(tc->id, 3);
643                 conntimer[nconns]=1;
644             } else {
645                 conntimer[nconns]=0;
646             }
647             nconns++;
648         }
649     } /* Outer loop over addrs */
650
651     AFS_GUNLOCK();
652     multi_Rx(rxconns,nconns)
653       {
654         multi_RXAFS_GetCapabilities(&caps[multi_i]);
655         results[multi_i] = multi_error;
656       } multi_End;
657     AFS_GLOCK();
658
659     for ( i = 0 ; i < nconns ; i++ ) {
660         ts = addrs[i]->server;
661         if ( !ts )
662             continue;
663         ts->capabilities = 0;
664         ts->flags |= SCAPS_KNOWN;
665         if ( results[i] == RXGEN_OPCODE ) {
666             /* Mark server as up - it responded */
667             results[i] = 0;
668             continue;
669         }
670         if ( results[i] >= 0 )
671             /* we currently handle 32-bits of capabilities */
672             if (caps[i].Capabilities_len > 0) {
673                 ts->capabilities = caps[i].Capabilities_val[0];
674                 xdr_free((xdrproc_t)xdr_Capabilities, &caps[i]);
675                 caps[i].Capabilities_val = NULL;
676                 caps[i].Capabilities_len = 0;
677             }
678     }
679
680     if ( afs_setTime != 0 ) {
681         start = osi_Time();         /* time the gettimeofday call */
682         AFS_GUNLOCK();
683         if ( afs_setTimeHost == NULL ) {
684             multi_Rx(rxconns,nconns)
685               {
686                 tv.tv_sec = tv.tv_usec = 0;
687                 multi_RXAFS_GetTime(
688                         (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
689                 tc = conns[multi_i];
690                 sa = tc->srvr;
691                 if (conntimer[multi_i] == 1)
692                   rx_SetConnDeadTime(tc->id, afs_rx_deadtime);
693                 end = osi_Time();
694                 results[multi_i]=multi_error;
695                 if ((start == end) && !multi_error)
696                   deltas[multi_i] = end - tv.tv_sec;
697
698               } multi_End;
699             }
700         else {                  /* find and query setTimeHost only */
701             for ( i = 0 ; i < j ; i++ ) {
702                 if ( conns[i] == NULL || conns[i]->srvr == NULL )
703                     continue;
704                 if ( conns[i]->srvr->server == afs_setTimeHost ) {
705                     tv.tv_sec = tv.tv_usec = 0;
706                     results[i] = RXAFS_GetTime(rxconns[i],
707                                 (afs_uint32 *)&tv.tv_sec, (afs_uint32 *)&tv.tv_usec);
708                     end = osi_Time();
709                     if ((start == end) && !results[i])
710                         deltas[i] = end - tv.tv_sec;
711                     break;
712                 }
713             }
714         }
715         AFS_GLOCK();
716     }
717
718     for(i=0;i<nconns;i++){
719       tc = conns[i];
720       sa = tc->srvr;
721
722       if (( results[i] >= 0 ) && (sa->sa_flags & SRVADDR_ISDOWN) && (tc->srvr == sa)) {
723         /* server back up */
724         print_internet_address("afs: file server ", sa, " is back up", 2);
725
726         ObtainWriteLock(&afs_xserver, 244);
727         ObtainWriteLock(&afs_xsrvAddr, 245);
728         afs_MarkServerUpOrDown(sa, 0);
729         ReleaseWriteLock(&afs_xsrvAddr);
730         ReleaseWriteLock(&afs_xserver);
731
732         if (afs_waitForeverCount) {
733           afs_osi_Wakeup(&afs_waitForever);
734         }
735       } else {
736         if (results[i] < 0) {
737           /* server crashed */
738           afs_ServerDown(sa);
739           ForceNewConnections(sa);  /* multi homed clients */
740         }
741       }
742     }
743
744     /*
745      * If we're supposed to set the time, and the call worked
746      * quickly (same second response) and this is the host we
747      * use for the time and the time is really different, then
748      * really set the time
749      */
750     if (afs_setTime != 0) {
751         for (i=0; i<nconns; i++) {
752             delta = deltas[i];
753             tc = conns[i];
754             sa = tc->srvr;
755
756             if ((tc->srvr->server == afs_setTimeHost ||
757                  /* Sync only to a server in the local cell */
758                  (afs_setTimeHost == (struct server *)0 &&
759                   afs_IsPrimaryCell(sa->server->cell)))) {
760                 /* set the time */
761                 char msgbuf[90];  /* strlen("afs: setting clock...") + slop */
762                 delta = end - tv.tv_sec;   /* how many secs fast we are */
763
764                 afs_setTimeHost = tc->srvr->server;
765                 /* see if clock has changed enough to make it worthwhile */
766                 if (delta >= AFS_MINCHANGE || delta <= -AFS_MINCHANGE) {
767                     end = osi_Time();
768                     if (delta > AFS_MAXCHANGEBACK) {
769                         /* setting clock too far back, just do it a little */
770                         tv.tv_sec = end - AFS_MAXCHANGEBACK;
771                     } else {
772                         tv.tv_sec = end - delta;
773                     }
774                     afs_osi_SetTime(&tv);
775                     if (delta > 0) {
776                         strcpy(msgbuf, "afs: setting clock back ");
777                         if (delta > AFS_MAXCHANGEBACK) {
778                             afs_strcat(msgbuf,
779                                        afs_cv2string(&tbuffer[CVBS],
780                                                      AFS_MAXCHANGEBACK));
781                             afs_strcat(msgbuf, " seconds (of ");
782                             afs_strcat(msgbuf,
783                                        afs_cv2string(&tbuffer[CVBS],
784                                                      delta -
785                                                      AFS_MAXCHANGEBACK));
786                             afs_strcat(msgbuf, ", via ");
787                             print_internet_address(msgbuf, sa,
788                                                    "); clock is still fast.",
789                                                    0);
790                         } else {
791                             afs_strcat(msgbuf,
792                                        afs_cv2string(&tbuffer[CVBS], delta));
793                             afs_strcat(msgbuf, " seconds (via ");
794                             print_internet_address(msgbuf, sa, ").", 0);
795                         }
796                     } else {
797                         strcpy(msgbuf, "afs: setting clock ahead ");
798                         afs_strcat(msgbuf,
799                                    afs_cv2string(&tbuffer[CVBS], -delta));
800                         afs_strcat(msgbuf, " seconds (via ");
801                         print_internet_address(msgbuf, sa, ").", 0);
802                     }
803                     /* We're only going to set it once; why bother looping? */
804                     break;
805                 }
806             }
807         }
808     }
809     for (i = 0; i < nconns; i++) {
810         afs_PutConn(conns[i], SHARED_LOCK);     /* done with it now */
811     }
812
813     afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
814     afs_osi_Free(conns, j * sizeof(struct afs_conn *));
815     afs_osi_Free(rxconns, j * sizeof(struct rx_connection *));
816     afs_osi_Free(conntimer, j * sizeof(afs_int32));
817     afs_osi_Free(deltas, j * sizeof(afs_int32));
818     afs_osi_Free(results, j * sizeof(afs_int32));
819     afs_osi_Free(caps, j * sizeof(Capabilities));
820
821 } /*afs_CheckServers*/
822
823
824 /* find a server structure given the host address */
825 struct server *
826 afs_FindServer(afs_int32 aserver, afs_uint16 aport, afsUUID * uuidp,
827                afs_int32 locktype)
828 {
829     struct server *ts;
830     struct srvAddr *sa;
831     int i;
832
833     AFS_STATCNT(afs_FindServer);
834     if (uuidp) {
835         i = afs_uuid_hash(uuidp) % NSERVERS;
836         for (ts = afs_servers[i]; ts; ts = ts->next) {
837             if ((ts->flags & SRVR_MULTIHOMED)
838                 &&
839                 (memcmp((char *)uuidp, (char *)&ts->sr_uuid, sizeof(*uuidp))
840                  == 0) && (!ts->addr || (ts->addr->sa_portal == aport)))
841                 return ts;
842         }
843     } else {
844         i = SHash(aserver);
845         for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
846             if ((sa->sa_ip == aserver) && (sa->sa_portal == aport)) {
847                 return sa->server;
848             }
849         }
850     }
851     return NULL;
852
853 }                               /*afs_FindServer */
854
855
856 /* some code for creating new server structs and setting preferences follows
857  * in the next few lines...
858  */
859
860 #define MAXDEFRANK 60000
861 #define DEFRANK    40000
862
863 /* Random number generator and constants from KnuthV2 2d ed, p170 */
864
865 /* Rules:
866    X = (aX + c) % m
867    m is a power of two
868    a % 8 is 5
869    a is 0.73m  should be 0.01m .. 0.99m
870    c is more or less immaterial.  1 or a is suggested.
871
872 NB:  LOW ORDER BITS are not very random.  To get small random numbers,
873      treat result as <1, with implied binary point, and multiply by
874      desired modulus.
875 NB:  Has to be unsigned, since shifts on signed quantities may preserve
876      the sign bit.
877 */
878 /* added rxi_getaddr() to try to get as much initial randomness as
879    possible, since at least one customer reboots ALL their clients
880    simultaneously -- so osi_Time is bound to be the same on some of the
881    clients.  This is probably OK, but I don't want to see too much of it.
882 */
883
884 #define ranstage(x)     (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
885
886 unsigned int
887 afs_random(void)
888 {
889     static afs_int32 state = 0;
890     int i;
891
892     AFS_STATCNT(afs_random);
893     if (!state) {
894         osi_timeval_t t;
895         osi_GetTime(&t);
896         /*
897          * 0xfffffff0 was changed to (~0 << 4) since it works no matter how many
898          * bits are in a tv_usec
899          */
900         state = (t.tv_usec & (~0 << 4)) + (rxi_getaddr() & 0xff);
901         state += (t.tv_sec & 0xff);
902         for (i = 0; i < 30; i++) {
903             ranstage(state);
904         }
905     }
906
907     ranstage(state);
908     return (state);
909
910 }                               /*afs_random */
911
912 /* returns int 0..14 using the high bits of a pseudo-random number instead of
913    the low bits, as the low bits are "less random" than the high ones...
914    slight roundoff error exists, an excercise for the reader.
915    need to multiply by something with lots of ones in it, so multiply by
916    8 or 16 is right out.
917  */
918 int
919 afs_randomMod15(void)
920 {
921     afs_uint32 temp;
922
923     temp = afs_random() >> 4;
924     temp = (temp * 15) >> 28;
925
926     return temp;
927 }
928
929 int
930 afs_randomMod127(void)
931 {
932     afs_uint32 temp;
933
934     temp = afs_random() >> 7;
935     temp = (temp * 127) >> 25;
936
937     return temp;
938 }
939
940 /* afs_SortOneServer()
941  * Sort all of the srvAddrs, of a server struct, by rank from low to high.
942  */
943 void
944 afs_SortOneServer(struct server *asp)
945 {
946     struct srvAddr **rootsa, *lowsa, *tsa, *lowprev;
947     int lowrank, rank;
948
949     for (rootsa = &(asp->addr); *rootsa; rootsa = &(lowsa->next_sa)) {
950         lowprev = NULL;
951         lowsa = *rootsa;        /* lowest sa is the first one */
952         lowrank = lowsa->sa_iprank;
953
954         for (tsa = *rootsa; tsa->next_sa; tsa = tsa->next_sa) {
955             rank = tsa->next_sa->sa_iprank;
956             if (rank < lowrank) {
957                 lowprev = tsa;
958                 lowsa = tsa->next_sa;
959                 lowrank = lowsa->sa_iprank;
960             }
961         }
962         if (lowprev) {          /* found one lower, so rearrange them */
963             lowprev->next_sa = lowsa->next_sa;
964             lowsa->next_sa = *rootsa;
965             *rootsa = lowsa;
966         }
967     }
968 }
969
970 /* afs_SortServer()
971  * Sort the pointer to servers by the server's rank (its lowest rank).
972  * It is assumed that the server already has its IP addrs sorted (the
973  * first being its lowest rank: afs_GetServer() calls afs_SortOneServer()).
974  */
975 void
976 afs_SortServers(struct server *aservers[], int count)
977 {
978     struct server *ts;
979     int i, j, low;
980
981     AFS_STATCNT(afs_SortServers);
982
983     for (i = 0; i < count; i++) {
984         if (!aservers[i])
985             break;
986         for (low = i, j = i + 1; j <= count; j++) {
987             if ((!aservers[j]) || (!aservers[j]->addr))
988                 break;
989             if ((!aservers[low]) || (!aservers[low]->addr))
990                 break;
991             if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
992                 low = j;
993             }
994         }
995         if (low != i) {
996             ts = aservers[i];
997             aservers[i] = aservers[low];
998             aservers[low] = ts;
999         }
1000     }
1001 }                               /*afs_SortServers */
1002
1003 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
1004    data structures to determine what the local IP addresses and subnet masks
1005    are in order to choose which server(s) are on the local subnet.
1006
1007    As I see it, there are several cases:
1008    1. The server address is one of this host's local addresses.  In this case
1009           this server is to be preferred over all others.
1010    2. The server is on the same subnet as one of the this host's local
1011       addresses.  (ie, an odd-sized subnet, not class A,B,orC)
1012    3. The server is on the same net as this host (class A,B or C)
1013    4. The server is on a different logical subnet or net than this host, but
1014    this host is a 'metric 0 gateway' to it.  Ie, two address-spaces share
1015    one physical medium.
1016    5. This host has a direct (point-to-point, ie, PPP or SLIP) link to the
1017    server.
1018    6. This host and the server are disjoint.
1019
1020    That is a rough order of preference.  If a point-to-point link has a high
1021    metric, I'm assuming that it is a very slow link, and putting it at the
1022    bottom of the list (at least until RX works better over slow links).  If
1023    its metric is 1, I'm assuming that it's relatively fast (T1) and putting
1024    it ahead of #6.
1025    It's not easy to check for case #4, so I'm ignoring it for the time being.
1026
1027    BSD "if" code keeps track of some rough network statistics (cf 'netstat -i')
1028    That could be used to prefer certain servers fairly easily.  Maybe some
1029    other time...
1030
1031    NOTE: this code is very system-dependent, and very dependent on the TCP/IP
1032    protocols (well, addresses that are stored in uint32s, at any rate).
1033  */
1034
1035 #define IA_DST(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_dstaddr))
1036 #define IA_BROAD(ia)((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
1037
1038 /* SA2ULONG takes a sockaddr_in, not a sockaddr (same thing, just cast it!) */
1039 #define SA2ULONG(sa) ((sa)->sin_addr.s_addr)
1040 #define TOPR 5000
1041 #define HI  20000
1042 #define MED 30000
1043 #define LO DEFRANK
1044 #define PPWEIGHT 4096
1045
1046 #define USEIFADDR
1047
1048
1049 #if     defined(AFS_SUN5_ENV) && ! defined(AFS_SUN56_ENV)
1050 #include <inet/common.h>
1051 /* IP interface structure, one per local address */
1052 typedef struct ipif_s {
1053      /**/ struct ipif_s *ipif_next;
1054     struct ill_s *ipif_ill;     /* Back pointer to our ill */
1055     long ipif_id;               /* Logical unit number */
1056     u_int ipif_mtu;             /* Starts at ipif_ill->ill_max_frag */
1057     afs_int32 ipif_local_addr;  /* Local IP address for this if. */
1058     afs_int32 ipif_net_mask;    /* Net mask for this interface. */
1059     afs_int32 ipif_broadcast_addr;      /* Broadcast addr for this interface. */
1060     afs_int32 ipif_pp_dst_addr; /* Point-to-point dest address. */
1061     u_int ipif_flags;           /* Interface flags. */
1062     u_int ipif_metric;          /* BSD if metric, for compatibility. */
1063     u_int ipif_ire_type;        /* LOCAL or LOOPBACK */
1064     mblk_t *ipif_arp_down_mp;   /* Allocated at time arp comes up to
1065                                  * prevent awkward out of mem condition
1066                                  * later
1067                                  */
1068     mblk_t *ipif_saved_ire_mp;  /* Allocated for each extra IRE_SUBNET/
1069                                  * RESOLVER on this interface so that
1070                                  * they can survive ifconfig down.
1071                                  */
1072     /*
1073      * The packet counts in the ipif contain the sum of the
1074      * packet counts in dead IREs that were affiliated with
1075      * this ipif.
1076      */
1077     u_long ipif_fo_pkt_count;   /* Forwarded thru our dead IREs */
1078     u_long ipif_ib_pkt_count;   /* Inbound packets for our dead IREs */
1079     u_long ipif_ob_pkt_count;   /* Outbound packets to our dead IREs */
1080     unsigned int
1081       ipif_multicast_up:1,      /* We have joined the allhosts group */
1082     : 0;
1083 } ipif_t;
1084
1085 typedef struct ipfb_s {
1086      /**/ struct ipf_s *ipfb_ipf;       /* List of ... */
1087     kmutex_t ipfb_lock;         /* Protect all ipf in list */
1088 } ipfb_t;
1089
1090 typedef struct ilm_s {
1091      /**/ afs_int32 ilm_addr;
1092     int ilm_refcnt;
1093     u_int ilm_timer;            /* IGMP */
1094     struct ipif_s *ilm_ipif;    /* Back pointer to ipif */
1095     struct ilm_s *ilm_next;     /* Linked list for each ill */
1096 } ilm_t;
1097
1098 typedef struct ill_s {
1099      /**/ struct ill_s *ill_next;       /* Chained in at ill_g_head. */
1100     struct ill_s **ill_ptpn;    /* Pointer to previous next. */
1101     queue_t *ill_rq;            /* Read queue. */
1102     queue_t *ill_wq;            /* Write queue. */
1103
1104     int ill_error;              /* Error value sent up by device. */
1105
1106     ipif_t *ill_ipif;           /* Interface chain for this ILL. */
1107     u_int ill_ipif_up_count;    /* Number of IPIFs currently up. */
1108     u_int ill_max_frag;         /* Max IDU. */
1109     char *ill_name;             /* Our name. */
1110     u_int ill_name_length;      /* Name length, incl. terminator. */
1111     u_int ill_subnet_type;      /* IRE_RESOLVER or IRE_SUBNET. */
1112     u_int ill_ppa;              /* Physical Point of Attachment num. */
1113     u_long ill_sap;
1114     int ill_sap_length;         /* Including sign (for position) */
1115     u_int ill_phys_addr_length; /* Excluding the sap. */
1116     mblk_t *ill_frag_timer_mp;  /* Reassembly timer state. */
1117     ipfb_t *ill_frag_hash_tbl;  /* Fragment hash list head. */
1118
1119     queue_t *ill_bind_pending_q;        /* Queue waiting for DL_BIND_ACK. */
1120     ipif_t *ill_ipif_pending;   /* IPIF waiting for DL_BIND_ACK. */
1121
1122     /* ill_hdr_length and ill_hdr_mp will be non zero if
1123      * the underlying device supports the M_DATA fastpath
1124      */
1125     int ill_hdr_length;
1126
1127     ilm_t *ill_ilm;             /* Multicast mebership for lower ill */
1128
1129     /* All non-nil cells between 'ill_first_mp_to_free' and
1130      * 'ill_last_mp_to_free' are freed in ill_delete.
1131      */
1132 #define ill_first_mp_to_free    ill_hdr_mp
1133     mblk_t *ill_hdr_mp;         /* Contains fastpath template */
1134     mblk_t *ill_bcast_mp;       /* DLPI header for broadcasts. */
1135     mblk_t *ill_bind_pending;   /* T_BIND_REQ awaiting completion. */
1136     mblk_t *ill_resolver_mp;    /* Resolver template. */
1137     mblk_t *ill_attach_mp;
1138     mblk_t *ill_bind_mp;
1139     mblk_t *ill_unbind_mp;
1140     mblk_t *ill_detach_mp;
1141 #define ill_last_mp_to_free     ill_detach_mp
1142
1143     u_int ill_frag_timer_running:1, ill_needs_attach:1, ill_is_ptp:1,
1144         ill_priv_stream:1, ill_unbind_pending:1, ill_pad_to_bit_31:27;
1145       MI_HRT_DCL(ill_rtime)
1146       MI_HRT_DCL(ill_rtmp)
1147 } ill_t;
1148 #endif
1149
1150 #ifdef AFS_USERSPACE_IP_ADDR
1151 #ifndef afs_min
1152 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1153 #endif
1154 /*
1155  * The IP addresses and ranks are determined by afsd (in user space) and
1156  * passed into the kernel at startup time through the AFSOP_ADVISEADDR
1157  * system call. These are stored in the data structure
1158  * called 'afs_cb_interface'.
1159  *
1160  * struct srvAddr *sa;         remote server
1161  * afs_int32 addr;                one of my local addr in net order
1162  * afs_uint32 subnetmask;         subnet mask of local addr in net order
1163  *
1164  */
1165 void
1166 afsi_SetServerIPRank(struct srvAddr *sa, afs_int32 addr,
1167                      afs_uint32 subnetmask)
1168 {
1169     afs_uint32 myAddr, myNet, mySubnet, netMask;
1170     afs_uint32 serverAddr;
1171
1172     myAddr = ntohl(addr);       /* one of my IP addr in host order */
1173     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1174     subnetmask = ntohl(subnetmask);     /* subnet mask in host order */
1175
1176     if (IN_CLASSA(myAddr))
1177         netMask = IN_CLASSA_NET;
1178     else if (IN_CLASSB(myAddr))
1179         netMask = IN_CLASSB_NET;
1180     else if (IN_CLASSC(myAddr))
1181         netMask = IN_CLASSC_NET;
1182     else
1183         netMask = 0;
1184
1185     myNet = myAddr & netMask;
1186     mySubnet = myAddr & subnetmask;
1187
1188     if ((serverAddr & netMask) == myNet) {
1189         if ((serverAddr & subnetmask) == mySubnet) {
1190             if (serverAddr == myAddr) { /* same machine */
1191                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1192             } else {            /* same subnet */
1193                 sa->sa_iprank = afs_min(sa->sa_iprank, HI);
1194             }
1195         } else {                /* same net */
1196             sa->sa_iprank = afs_min(sa->sa_iprank, MED);
1197         }
1198     }
1199     return;
1200 }
1201 #else /* AFS_USERSPACE_IP_ADDR */
1202 #if (! defined(AFS_SUN5_ENV)) && !defined(AFS_DARWIN_ENV) && defined(USEIFADDR)
1203 void
1204 afsi_SetServerIPRank(struct srvAddr *sa, struct in_ifaddr *ifa)
1205 {
1206     struct sockaddr_in *sin;
1207     int t;
1208
1209     if ((ntohl(sa->sa_ip) & ifa->ia_netmask) == ifa->ia_net) {
1210         if ((ntohl(sa->sa_ip) & ifa->ia_subnetmask) == ifa->ia_subnet) {
1211             sin = IA_SIN(ifa);
1212             if (SA2ULONG(sin) == ntohl(sa->sa_ip)) {    /* ie, ME!!!  */
1213                 sa->sa_iprank = TOPR;
1214             } else {
1215                 t = HI + ifa->ia_ifp->if_metric;        /* case #2 */
1216                 if (sa->sa_iprank > t)
1217                     sa->sa_iprank = t;
1218             }
1219         } else {
1220             t = MED + ifa->ia_ifp->if_metric;   /* case #3 */
1221             if (sa->sa_iprank > t)
1222                 sa->sa_iprank = t;
1223         }
1224     }
1225 #ifdef  IFF_POINTTOPOINT
1226     /* check for case #4 -- point-to-point link */
1227     if ((ifa->ia_ifp->if_flags & IFF_POINTOPOINT)
1228         && (SA2ULONG(IA_DST(ifa)) == ntohl(sa->sa_ip))) {
1229         if (ifa->ia_ifp->if_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1230             t = MAXDEFRANK;
1231         else
1232             t = MED + (PPWEIGHT << ifa->ia_ifp->if_metric);
1233         if (sa->sa_iprank > t)
1234             sa->sa_iprank = t;
1235     }
1236 #endif /* IFF_POINTTOPOINT */
1237 }
1238 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1239 #if defined(AFS_DARWIN_ENV) && defined(USEIFADDR)
1240 #ifndef afs_min
1241 #define afs_min(A,B) ((A)<(B)) ? (A) : (B)
1242 #endif
1243 void
1244 afsi_SetServerIPRank(struct srvAddr *sa, rx_ifaddr_t ifa)
1245 {
1246     struct sockaddr sout;
1247     struct sockaddr_in *sin;
1248     int t;
1249
1250     afs_uint32 subnetmask, myAddr, myNet, myDstaddr, mySubnet, netMask;
1251     afs_uint32 serverAddr;
1252
1253     if (rx_ifaddr_address_family(ifa) != AF_INET)
1254         return;
1255     t = rx_ifaddr_address(ifa, &sout, sizeof(sout));
1256     if (t == 0) {
1257         sin = (struct sockaddr_in *)&sout;
1258         myAddr = ntohl(sin->sin_addr.s_addr);   /* one of my IP addr in host order */
1259     } else {
1260         myAddr = 0;
1261     }
1262     serverAddr = ntohl(sa->sa_ip);      /* server's IP addr in host order */
1263     t = rx_ifaddr_netmask(ifa, &sout, sizeof(sout));
1264     if (t == 0) {
1265         sin = (struct sockaddr_in *)&sout;
1266         subnetmask = ntohl(sin->sin_addr.s_addr);       /* subnet mask in host order */
1267     } else {
1268         subnetmask = 0;
1269     }
1270     t = rx_ifaddr_dstaddress(ifa, &sout, sizeof(sout));
1271     if (t == 0) {
1272         sin = (struct sockaddr_in *)&sout;
1273         myDstaddr = sin->sin_addr.s_addr;
1274     } else {
1275         myDstaddr = 0;
1276     }
1277
1278     if (IN_CLASSA(myAddr))
1279         netMask = IN_CLASSA_NET;
1280     else if (IN_CLASSB(myAddr))
1281         netMask = IN_CLASSB_NET;
1282     else if (IN_CLASSC(myAddr))
1283         netMask = IN_CLASSC_NET;
1284     else
1285         netMask = 0;
1286
1287     myNet = myAddr & netMask;
1288     mySubnet = myAddr & subnetmask;
1289
1290     if ((serverAddr & netMask) == myNet) {
1291         if ((serverAddr & subnetmask) == mySubnet) {
1292             if (serverAddr == myAddr) { /* same machine */
1293                 sa->sa_iprank = afs_min(sa->sa_iprank, TOPR);
1294             } else {            /* same subnet */
1295                 sa->sa_iprank = afs_min(sa->sa_iprank, HI + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1296             }
1297         } else {                /* same net */
1298             sa->sa_iprank = afs_min(sa->sa_iprank, MED + rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1299         }
1300     }
1301 #ifdef  IFF_POINTTOPOINT
1302     /* check for case #4 -- point-to-point link */
1303     if ((rx_ifnet_flags(rx_ifaddr_ifnet(ifa)) & IFF_POINTOPOINT)
1304         && (myDstaddr == serverAddr)) {
1305         if (rx_ifnet_metric(rx_ifaddr_ifnet(ifa)) >= (MAXDEFRANK - MED) / PPWEIGHT)
1306             t = MAXDEFRANK;
1307         else
1308             t = MED + (PPWEIGHT << rx_ifnet_metric(rx_ifaddr_ifnet(ifa)));
1309         if (sa->sa_iprank > t)
1310             sa->sa_iprank = t;
1311         }
1312 #endif /* IFF_POINTTOPOINT */
1313 }
1314 #endif /*(!defined(AFS_SUN5_ENV)) && defined(USEIFADDR) */
1315 #endif /* else AFS_USERSPACE_IP_ADDR */
1316
1317 #ifdef AFS_SGI62_ENV
1318 static int
1319 afsi_enum_set_rank(struct hashbucket *h, caddr_t mkey, caddr_t arg1,
1320                    caddr_t arg2)
1321 {
1322     afsi_SetServerIPRank((struct srvAddr *)arg1, (struct in_ifaddr *)h);
1323     return 0;                   /* Never match, so we enumerate everyone */
1324 }
1325 #endif                          /* AFS_SGI62_ENV */
1326 static int
1327 afs_SetServerPrefs(struct srvAddr *sa)
1328 {
1329 #if     defined(AFS_USERSPACE_IP_ADDR)
1330     int i;
1331
1332       sa->sa_iprank = LO;
1333     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1334         afsi_SetServerIPRank(sa, afs_cb_interface.addr_in[i],
1335                              afs_cb_interface.subnetmask[i]);
1336     }
1337 #else                           /* AFS_USERSPACE_IP_ADDR */
1338 #if     defined(AFS_SUN5_ENV)
1339 #ifdef AFS_SUN510_ENV
1340     int i = 0;
1341 #else
1342     extern struct ill_s *ill_g_headp;
1343     long *addr = (long *)ill_g_headp;
1344     ill_t *ill;
1345     ipif_t *ipif;
1346 #endif
1347     int subnet, subnetmask, net, netmask;
1348
1349     if (sa)
1350           sa->sa_iprank = 0;
1351 #ifdef AFS_SUN510_ENV
1352     rw_enter(&afsifinfo_lock, RW_READER);
1353
1354     for (i = 0; (afsifinfo[i].ipaddr != NULL) && (i < ADDRSPERSITE); i++) {
1355
1356         if (IN_CLASSA(afsifinfo[i].ipaddr)) {
1357             netmask = IN_CLASSA_NET;
1358         } else if (IN_CLASSB(afsifinfo[i].ipaddr)) {
1359             netmask = IN_CLASSB_NET;
1360         } else if (IN_CLASSC(afsifinfo[i].ipaddr)) {
1361             netmask = IN_CLASSC_NET;
1362         } else {
1363             netmask = 0;
1364         }
1365         net = afsifinfo[i].ipaddr & netmask;
1366
1367 #ifdef notdef
1368         if (!s) {
1369             if (!rx_IsLoopbackAddr(afsifinfo[i].ipaddr)) {      /* ignore loopback */
1370                 *cnt += 1;
1371                 if (*cnt > 16)
1372                     return;
1373                 *addrp++ = afsifinfo[i].ipaddr;
1374             }
1375         } else
1376 #endif /* notdef */
1377         {
1378             /* XXXXXX Do the individual ip ranking below XXXXX */
1379             if ((sa->sa_ip & netmask) == net) {
1380                 if ((sa->sa_ip & subnetmask) == subnet) {
1381                     if (afsifinfo[i].ipaddr == sa->sa_ip) {   /* ie, ME!  */
1382                         sa->sa_iprank = TOPR;
1383                     } else {
1384                         sa->sa_iprank = HI + afsifinfo[i].metric; /* case #2 */
1385                     }
1386                 } else {
1387                     sa->sa_iprank = MED + afsifinfo[i].metric;    /* case #3 */
1388                 }
1389             } else {
1390                     sa->sa_iprank = LO + afsifinfo[i].metric;     /* case #4 */
1391             }
1392             /* check for case #5 -- point-to-point link */
1393             if ((afsifinfo[i].flags & IFF_POINTOPOINT)
1394                 && (afsifinfo[i].dstaddr == sa->sa_ip)) {
1395
1396                     if (afsifinfo[i].metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1397                         sa->sa_iprank = MAXDEFRANK;
1398                     else
1399                         sa->sa_iprank = MED + (PPWEIGHT << afsifinfo[i].metric);
1400             }
1401         }
1402     }
1403
1404     rw_exit(&afsifinfo_lock);
1405 #else
1406     for (ill = (struct ill_s *)*addr /*ill_g_headp */ ; ill;
1407          ill = ill->ill_next) {
1408 #ifdef AFS_SUN58_ENV
1409         /* Make sure this is an IPv4 ILL */
1410         if (ill->ill_isv6)
1411             continue;
1412 #endif
1413         for (ipif = ill->ill_ipif; ipif; ipif = ipif->ipif_next) {
1414             subnet = ipif->ipif_local_addr & ipif->ipif_net_mask;
1415             subnetmask = ipif->ipif_net_mask;
1416             /*
1417              * Generate the local net using the local address and
1418              * whate we know about Class A, B and C networks.
1419              */
1420             if (IN_CLASSA(ipif->ipif_local_addr)) {
1421                 netmask = IN_CLASSA_NET;
1422             } else if (IN_CLASSB(ipif->ipif_local_addr)) {
1423                 netmask = IN_CLASSB_NET;
1424             } else if (IN_CLASSC(ipif->ipif_local_addr)) {
1425                 netmask = IN_CLASSC_NET;
1426             } else {
1427                 netmask = 0;
1428             }
1429             net = ipif->ipif_local_addr & netmask;
1430 #ifdef notdef
1431             if (!s) {
1432                 if (!rx_IsLoopbackAddr(ipif->ipif_local_addr)) {        /* ignore loopback */
1433                     *cnt += 1;
1434                     if (*cnt > 16)
1435                         return;
1436                     *addrp++ = ipif->ipif_local_addr;
1437                 }
1438             } else
1439 #endif /* notdef */
1440             {
1441                 /* XXXXXX Do the individual ip ranking below XXXXX */
1442                 if ((sa->sa_ip & netmask) == net) {
1443                     if ((sa->sa_ip & subnetmask) == subnet) {
1444                         if (ipif->ipif_local_addr == sa->sa_ip) {       /* ie, ME!  */
1445                             sa->sa_iprank = TOPR;
1446                         } else {
1447                             sa->sa_iprank = HI + ipif->ipif_metric;     /* case #2 */
1448                         }
1449                     } else {
1450                         sa->sa_iprank = MED + ipif->ipif_metric;        /* case #3 */
1451                     }
1452                 } else {
1453                     sa->sa_iprank = LO + ipif->ipif_metric;     /* case #4 */
1454                 }
1455                 /* check for case #5 -- point-to-point link */
1456                 if ((ipif->ipif_flags & IFF_POINTOPOINT)
1457                     && (ipif->ipif_pp_dst_addr == sa->sa_ip)) {
1458
1459                     if (ipif->ipif_metric >= (MAXDEFRANK - MED) / PPWEIGHT)
1460                         sa->sa_iprank = MAXDEFRANK;
1461                     else
1462                         sa->sa_iprank = MED + (PPWEIGHT << ipif->ipif_metric);
1463                 }
1464             }
1465         }
1466     }
1467 #endif /* AFS_SUN510_ENV */
1468 #else
1469 #ifndef USEIFADDR
1470     rx_ifnet_t ifn = NULL;
1471     struct in_ifaddr *ifad = (struct in_ifaddr *)0;
1472     struct sockaddr_in *sin;
1473
1474     if (!sa) {
1475 #ifdef notdef                   /* clean up, remove this */
1476         for (ifn = ifnet; ifn != NULL; ifn = ifn->if_next) {
1477             for (ifad = ifn->if_addrlist; ifad != NULL; ifad = ifad->ifa_next) {
1478                 if ((IFADDR2SA(ifad)->sa_family == AF_INET)
1479                     && !(ifn->if_flags & IFF_LOOPBACK)) {
1480                     *cnt += 1;
1481                     if (*cnt > 16)
1482                         return;
1483                     *addrp++ =
1484                         ((struct sockaddr_in *)IFADDR2SA(ifad))->sin_addr.
1485                         s_addr;
1486                 }
1487         }}
1488 #endif                          /* notdef */
1489         return;
1490     }
1491     sa->sa_iprank = 0;
1492 #ifdef  ADAPT_MTU
1493     ifn = rxi_FindIfnet(sa->sa_ip, &ifad);
1494 #endif
1495     if (ifn) {                  /* local, more or less */
1496 #ifdef IFF_LOOPBACK
1497         if (ifn->if_flags & IFF_LOOPBACK) {
1498             sa->sa_iprank = TOPR;
1499             goto end;
1500         }
1501 #endif /* IFF_LOOPBACK */
1502         sin = (struct sockaddr_in *)IA_SIN(ifad);
1503         if (SA2ULONG(sin) == sa->sa_ip) {
1504             sa->sa_iprank = TOPR;
1505             goto end;
1506         }
1507 #ifdef IFF_BROADCAST
1508         if (ifn->if_flags & IFF_BROADCAST) {
1509             if (sa->sa_ip == (sa->sa_ip & SA2ULONG(IA_BROAD(ifad)))) {
1510                 sa->sa_iprank = HI;
1511                 goto end;
1512             }
1513         }
1514 #endif /* IFF_BROADCAST */
1515 #ifdef IFF_POINTOPOINT
1516         if (ifn->if_flags & IFF_POINTOPOINT) {
1517             if (sa->sa_ip == SA2ULONG(IA_DST(ifad))) {
1518                 if (ifn->if_metric > 4) {
1519                     sa->sa_iprank = LO;
1520                     goto end;
1521                 } else
1522                     sa->sa_iprank = ifn->if_metric;
1523             }
1524         }
1525 #endif /* IFF_POINTOPOINT */
1526         sa->sa_iprank += MED + ifn->if_metric;  /* couldn't find anything better */
1527     }
1528 #else                           /* USEIFADDR */
1529
1530     if (sa)
1531         sa->sa_iprank = LO;
1532 #ifdef AFS_SGI62_ENV
1533     (void)hash_enum(&hashinfo_inaddr, afsi_enum_set_rank, HTF_INET, NULL,
1534                     (caddr_t) sa, NULL);
1535 #elif defined(AFS_DARWIN80_ENV)
1536     {
1537         errno_t t;
1538         unsigned int count;
1539         int cnt=0, m, j;
1540         rx_ifaddr_t *ifads;
1541         rx_ifnet_t *ifns;
1542
1543         if (!ifnet_list_get(AF_INET, &ifns, &count)) {
1544             for (m = 0; m < count; m++) {
1545                 if (!ifnet_get_address_list(ifns[m], &ifads)) {
1546                     for (j = 0; ifads[j] != NULL && cnt < ADDRSPERSITE; j++) {
1547                         afsi_SetServerIPRank(sa, ifads[j]);
1548                         cnt++;
1549                     }
1550                     ifnet_free_address_list(ifads);
1551                 }
1552             }
1553             ifnet_list_free(ifns);
1554         }
1555     }
1556 #elif defined(AFS_DARWIN_ENV)
1557     {
1558         rx_ifnet_t ifn;
1559         rx_ifaddr_t ifa;
1560           TAILQ_FOREACH(ifn, &ifnet, if_link) {
1561             TAILQ_FOREACH(ifa, &ifn->if_addrhead, ifa_link) {
1562                 afsi_SetServerIPRank(sa, ifa);
1563     }}}
1564 #elif defined(AFS_FBSD_ENV)
1565     {
1566         struct in_ifaddr *ifa;
1567           TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
1568             afsi_SetServerIPRank(sa, ifa);
1569     }}
1570 #elif defined(AFS_OBSD_ENV)
1571     {
1572         extern struct in_ifaddrhead in_ifaddr;
1573         struct in_ifaddr *ifa;
1574         for (ifa = in_ifaddr.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1575             afsi_SetServerIPRank(sa, ifa);
1576     }
1577 #elif defined(AFS_NBSD40_ENV)
1578      {
1579        extern struct in_ifaddrhead in_ifaddrhead;
1580        struct in_ifaddr *ifa;
1581        for (ifa = in_ifaddrhead.tqh_first; ifa; ifa = ifa->ia_list.tqe_next)
1582            afsi_SetServerIPRank(sa, ifa);
1583      }
1584 #else
1585     {
1586         struct in_ifaddr *ifa;
1587         for (ifa = in_ifaddr; ifa; ifa = ifa->ia_next) {
1588             afsi_SetServerIPRank(sa, ifa);
1589     }}
1590 #endif
1591 #endif                          /* USEIFADDR */
1592 #ifndef USEIFADDR
1593     end:
1594 #endif
1595 #endif                          /* AFS_SUN5_ENV */
1596 #endif                          /* else AFS_USERSPACE_IP_ADDR */
1597     if (sa)
1598           sa->sa_iprank += afs_randomMod15();
1599
1600     return 0;
1601 }                               /* afs_SetServerPrefs */
1602
1603 #undef TOPR
1604 #undef HI
1605 #undef MED
1606 #undef LO
1607 #undef PPWEIGHT
1608
1609 /* afs_FlushServer()
1610  * The addresses on this server struct has changed in some way and will
1611  * clean up all other structures that may reference it.
1612  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1613  */
1614 void
1615 afs_FlushServer(struct server *srvp)
1616 {
1617     afs_int32 i;
1618     struct server *ts, **pts;
1619
1620     /* Find any volumes residing on this server and flush their state */
1621       afs_ResetVolumes(srvp);
1622
1623     /* Flush all callbacks in the all vcaches for this specific server */
1624       afs_FlushServerCBs(srvp);
1625
1626     /* Remove all the callbacks structs */
1627     if (srvp->cbrs) {
1628         struct afs_cbr *cb, *cbnext;
1629
1630           ObtainWriteLock(&afs_xvcb, 300);
1631         for (cb = srvp->cbrs; cb; cb = cbnext) {
1632             cbnext = cb->next;
1633             afs_FreeCBR(cb);
1634         } srvp->cbrs = (struct afs_cbr *)0;
1635         ReleaseWriteLock(&afs_xvcb);
1636     }
1637
1638     /* If no more srvAddr structs hanging off of this server struct,
1639      * then clean it up.
1640      */
1641     if (!srvp->addr) {
1642         /* Remove the server structure from the cell list - if there */
1643         afs_RemoveCellEntry(srvp);
1644
1645         /* Remove from the afs_servers hash chain */
1646         for (i = 0; i < NSERVERS; i++) {
1647             for (pts = &(afs_servers[i]), ts = *pts; ts;
1648                  pts = &(ts->next), ts = *pts) {
1649                 if (ts == srvp)
1650                     break;
1651             }
1652             if (ts)
1653                 break;
1654         }
1655         if (ts) {
1656             *pts = ts->next;    /* Found it. Remove it */
1657             afs_osi_Free(ts, sizeof(struct server));    /* Free it */
1658             afs_totalServers--;
1659         }
1660     }
1661 }
1662
1663 /* afs_RemoveSrvAddr()
1664  * This removes a SrvAddr structure from its server structure.
1665  * The srvAddr struct is not free'd because it connections may still
1666  * be open to it. It is up to the calling process to make sure it
1667  * remains connected to a server struct.
1668  * The afs_xserver and afs_xsrvAddr locks are assumed taken.
1669  *    It is not removed from the afs_srvAddrs hash chain.
1670  */
1671 void
1672 afs_RemoveSrvAddr(struct srvAddr *sap)
1673 {
1674     struct srvAddr **psa, *sa;
1675     struct server *srv;
1676
1677     if (!sap)
1678           return;
1679       srv = sap->server;
1680
1681     /* Find the srvAddr in the server's list and remove it */
1682     for (psa = &(srv->addr), sa = *psa; sa; psa = &(sa->next_sa), sa = *psa) {
1683         if (sa == sap)
1684             break;
1685     } if (sa) {
1686         *psa = sa->next_sa;
1687         sa->next_sa = 0;
1688         sa->server = 0;
1689
1690         /* Flush the server struct since it's IP address has changed */
1691         afs_FlushServer(srv);
1692     }
1693 }
1694
1695 /* afs_GetCapabilities
1696  * Try and retrieve capabilities of a given file server. Carps on actual
1697  * failure. Servers are not expected to support this RPC. */
1698 void
1699 afs_GetCapabilities(struct server *ts)
1700 {
1701     Capabilities caps = {0, NULL};
1702     struct vrequest treq;
1703     struct afs_conn *tc;
1704     struct unixuser *tu;
1705     afs_int32 code;
1706
1707     if ( !ts || !ts->cell )
1708         return;
1709     if ( !afs_osi_credp )
1710         return;
1711
1712     if ((code = afs_InitReq(&treq, afs_osi_credp)))
1713         return;
1714     tu = afs_GetUser(treq.uid, ts->cell->cellNum, SHARED_LOCK);
1715     if ( !tu )
1716         return;
1717     tc = afs_ConnBySA(ts->addr, ts->cell->fsport, ts->cell->cellNum, tu, 0, 1,
1718                                                                 SHARED_LOCK);
1719     if ( !tc )
1720         return;
1721     /* InitCallBackStateN, triggered by our RPC, may need this */
1722     ReleaseWriteLock(&afs_xserver);
1723     code = RXAFS_GetCapabilities(tc->id, &caps);
1724     ObtainWriteLock(&afs_xserver, 723);
1725     afs_PutConn(tc, SHARED_LOCK);
1726     if ( code && code != RXGEN_OPCODE ) {
1727         afs_warn("RXAFS_GetCapabilities failed with code %d\n", code);
1728         /* better not be anything to free. we failed! */
1729         return;
1730     }
1731
1732     ts->flags |= SCAPS_KNOWN;
1733
1734     if ( caps.Capabilities_len > 0 ) {
1735         ts->capabilities = caps.Capabilities_val[0];
1736         xdr_free((xdrproc_t)xdr_Capabilities, &caps);
1737         caps.Capabilities_len = 0;
1738         caps.Capabilities_val = NULL;
1739     }
1740
1741 }
1742
1743 /* afs_GetServer()
1744  * Return an updated and properly initialized server structure
1745  * corresponding to the server ID, cell, and port specified.
1746  * If one does not exist, then one will be created.
1747  * aserver and aport must be in NET byte order.
1748  */
1749 struct server *
1750 afs_GetServer(afs_uint32 * aserverp, afs_int32 nservers, afs_int32 acell,
1751               u_short aport, afs_int32 locktype, afsUUID * uuidp,
1752               afs_int32 addr_uniquifier)
1753 {
1754     struct server *oldts = 0, *ts, *newts, *orphts = 0;
1755     struct srvAddr *oldsa, *newsa, *nextsa, *orphsa;
1756     u_short fsport;
1757     afs_int32 iphash, k, srvcount = 0;
1758     unsigned int srvhash;
1759
1760     AFS_STATCNT(afs_GetServer);
1761
1762     ObtainSharedLock(&afs_xserver, 13);
1763
1764     /* Check if the server struct exists and is up to date */
1765     if (!uuidp) {
1766         if (nservers != 1)
1767             panic("afs_GetServer: incorect count of servers");
1768         ObtainReadLock(&afs_xsrvAddr);
1769         ts = afs_FindServer(aserverp[0], aport, NULL, locktype);
1770         ReleaseReadLock(&afs_xsrvAddr);
1771         if (ts && !(ts->flags & SRVR_MULTIHOMED)) {
1772             /* Found a server struct that is not multihomed and has the
1773              * IP address associated with it. A correct match.
1774              */
1775             ReleaseSharedLock(&afs_xserver);
1776             return (ts);
1777         }
1778     } else {
1779         if (nservers <= 0)
1780             panic("afs_GetServer: incorrect count of servers");
1781         ts = afs_FindServer(0, aport, uuidp, locktype);
1782         if (ts && (ts->sr_addr_uniquifier == addr_uniquifier) && ts->addr) {
1783             /* Found a server struct that is multihomed and same
1784              * uniqufier (same IP addrs). The above if statement is the
1785              * same as in InstallUVolumeEntry().
1786              */
1787             ReleaseSharedLock(&afs_xserver);
1788             return ts;
1789         }
1790         if (ts)
1791             oldts = ts;         /* Will reuse if same uuid */
1792     }
1793
1794     UpgradeSToWLock(&afs_xserver, 36);
1795     ObtainWriteLock(&afs_xsrvAddr, 116);
1796
1797     srvcount = afs_totalServers;
1798
1799     /* Reuse/allocate a new server structure */
1800     if (oldts) {
1801         newts = oldts;
1802     } else {
1803         newts = afs_osi_Alloc(sizeof(struct server));
1804         if (!newts)
1805             panic("malloc of server struct");
1806         afs_totalServers++;
1807         memset(newts, 0, sizeof(struct server));
1808
1809         /* Add the server struct to the afs_servers[] hash chain */
1810         srvhash =
1811             (uuidp ? (afs_uuid_hash(uuidp) % NSERVERS) : SHash(aserverp[0]));
1812         newts->next = afs_servers[srvhash];
1813         afs_servers[srvhash] = newts;
1814     }
1815
1816     /* Initialize the server structure */
1817     if (uuidp) {                /* Multihomed */
1818         newts->sr_uuid = *uuidp;
1819         newts->sr_addr_uniquifier = addr_uniquifier;
1820         newts->flags |= SRVR_MULTIHOMED;
1821     }
1822     if (acell)
1823         newts->cell = afs_GetCell(acell, 0);
1824
1825     fsport = (newts->cell ? newts->cell->fsport : AFS_FSPORT);
1826
1827     /* For each IP address we are registering */
1828     for (k = 0; k < nservers; k++) {
1829         iphash = SHash(aserverp[k]);
1830
1831         /* Check if the srvAddr structure already exists. If so, remove
1832          * it from its server structure and add it to the new one.
1833          */
1834         for (oldsa = afs_srvAddrs[iphash]; oldsa; oldsa = oldsa->next_bkt) {
1835             if ((oldsa->sa_ip == aserverp[k]) && (oldsa->sa_portal == aport))
1836                 break;
1837         }
1838         if (oldsa && (oldsa->server != newts)) {
1839             afs_RemoveSrvAddr(oldsa);   /* Remove from its server struct */
1840             oldsa->next_sa = newts->addr;       /* Add to the  new server struct */
1841             newts->addr = oldsa;
1842         }
1843
1844         /* Reuse/allocate a new srvAddr structure */
1845         if (oldsa) {
1846             newsa = oldsa;
1847         } else {
1848             newsa = afs_osi_Alloc(sizeof(struct srvAddr));
1849             if (!newsa)
1850                 panic("malloc of srvAddr struct");
1851             afs_totalSrvAddrs++;
1852             memset(newsa, 0, sizeof(struct srvAddr));
1853
1854             /* Add the new srvAddr to the afs_srvAddrs[] hash chain */
1855             newsa->next_bkt = afs_srvAddrs[iphash];
1856             afs_srvAddrs[iphash] = newsa;
1857
1858             /* Hang off of the server structure  */
1859             newsa->next_sa = newts->addr;
1860             newts->addr = newsa;
1861
1862             /* Initialize the srvAddr Structure */
1863             newsa->sa_ip = aserverp[k];
1864             newsa->sa_portal = aport;
1865         }
1866
1867         /* Update the srvAddr Structure */
1868         newsa->server = newts;
1869         if (newts->flags & SRVR_ISDOWN)
1870             newsa->sa_flags |= SRVADDR_ISDOWN;
1871         if (uuidp)
1872             newsa->sa_flags |= SRVADDR_MH;
1873         else
1874             newsa->sa_flags &= ~SRVADDR_MH;
1875
1876         /* Compute preference values and resort */
1877         if (!newsa->sa_iprank) {
1878             afs_SetServerPrefs(newsa);  /* new server rank */
1879         }
1880     }
1881     afs_SortOneServer(newts);   /* Sort by rank */
1882
1883     /* If we reused the server struct, remove any of its srvAddr
1884      * structs that will no longer be associated with this server.
1885      */
1886     if (oldts) {                /* reused the server struct */
1887         for (orphsa = newts->addr; orphsa; orphsa = nextsa) {
1888             nextsa = orphsa->next_sa;
1889             for (k = 0; k < nservers; k++) {
1890                 if (orphsa->sa_ip == aserverp[k])
1891                     break;      /* belongs */
1892             }
1893             if (k < nservers)
1894                 continue;       /* belongs */
1895
1896             /* Have a srvAddr struct. Now get a server struct (if not already) */
1897             if (!orphts) {
1898                 orphts = afs_osi_Alloc(sizeof(struct server));
1899                 if (!orphts)
1900                     panic("malloc of lo server struct");
1901                 memset(orphts, 0, sizeof(struct server));
1902                 afs_totalServers++;
1903
1904                 /* Add the orphaned server to the afs_servers[] hash chain.
1905                  * Its iphash does not matter since we never look up the server
1906                  * in the afs_servers table by its ip address (only by uuid -
1907                  * which this has none).
1908                  */
1909                 iphash = SHash(aserverp[k]);
1910                 orphts->next = afs_servers[iphash];
1911                 afs_servers[iphash] = orphts;
1912
1913                 if (acell)
1914                     orphts->cell = afs_GetCell(acell, 0);
1915             }
1916
1917             /* Hang the srvAddr struct off of the server structure. The server
1918              * may have multiple srvAddrs, but it won't be marked multihomed.
1919              */
1920             afs_RemoveSrvAddr(orphsa);  /* remove */
1921             orphsa->next_sa = orphts->addr;     /* hang off server struct */
1922             orphts->addr = orphsa;
1923             orphsa->server = orphts;
1924             orphsa->sa_flags |= SRVADDR_NOUSE;  /* flag indicating not in use */
1925             orphsa->sa_flags &= ~SRVADDR_MH;    /* Not multihomed */
1926         }
1927     }
1928
1929     srvcount = afs_totalServers - srvcount;     /* # servers added and removed */
1930     if (srvcount) {
1931         struct afs_stats_SrvUpDownInfo *upDownP;
1932         /* With the introduction of this new record, we need to adjust the
1933          * proper individual & global server up/down info.
1934          */
1935         upDownP = GetUpDownStats(newts);
1936         upDownP->numTtlRecords += srvcount;
1937         afs_stats_cmperf.srvRecords += srvcount;
1938         if (afs_stats_cmperf.srvRecords > afs_stats_cmperf.srvRecordsHWM)
1939             afs_stats_cmperf.srvRecordsHWM = afs_stats_cmperf.srvRecords;
1940     }
1941
1942     ReleaseWriteLock(&afs_xsrvAddr);
1943
1944     if ( aport == AFS_FSPORT && !(newts->flags & SCAPS_KNOWN))
1945         afs_GetCapabilities(newts);
1946
1947     ReleaseWriteLock(&afs_xserver);
1948     return (newts);
1949 }                               /* afs_GetServer */
1950
1951 void
1952 afs_ActivateServer(struct srvAddr *sap)
1953 {
1954     osi_timeval_t currTime;     /*Filled with current time */
1955     osi_timeval_t *currTimeP;   /*Ptr to above */
1956     struct afs_stats_SrvUpDownInfo *upDownP;    /*Ptr to up/down info record */
1957     struct server *aserver = sap->server;
1958
1959     if (!(aserver->flags & AFS_SERVER_FLAG_ACTIVATED)) {
1960         /*
1961          * This server record has not yet been activated.  Go for it,
1962          * recording its ``birth''.
1963          */
1964         aserver->flags |= AFS_SERVER_FLAG_ACTIVATED;
1965         currTimeP = &currTime;
1966         osi_GetuTime(currTimeP);
1967         aserver->activationTime = currTime.tv_sec;
1968         upDownP = GetUpDownStats(aserver);
1969         if (aserver->flags & SRVR_ISDOWN) {
1970             upDownP->numDownRecords++;
1971         } else {
1972             upDownP->numUpRecords++;
1973             upDownP->numRecordsNeverDown++;
1974         }
1975     }
1976 }
1977
1978 void
1979 afs_RemoveAllConns(void)
1980 {
1981     int i;
1982     struct server *ts, *nts;
1983     struct srvAddr *sa;
1984     struct afs_conn *tc, *ntc;
1985
1986     ObtainReadLock(&afs_xserver);
1987     ObtainWriteLock(&afs_xconn, 1001);
1988
1989     /*printf("Destroying connections ... ");*/
1990     for (i = 0; i < NSERVERS; i++) {
1991         for (ts = afs_servers[i]; ts; ts = nts) {
1992             nts = ts->next;
1993             for (sa = ts->addr; sa; sa = sa->next_sa) {
1994                 if (sa->conns) {
1995                     tc = sa->conns;
1996                     while (tc) {
1997                         ntc = tc->next;
1998                         AFS_GUNLOCK();
1999                         rx_DestroyConnection(tc->id);
2000                         AFS_GLOCK();
2001                         afs_osi_Free(tc, sizeof(struct afs_conn));
2002                         tc = ntc;
2003                     }
2004                     sa->conns = NULL;
2005                 }
2006             }
2007         }
2008     }
2009     /*printf("done\n");*/
2010
2011     ReleaseWriteLock(&afs_xconn);
2012     ReleaseReadLock(&afs_xserver);
2013
2014 }
2015
2016 void
2017 afs_MarkAllServersUp(void)
2018 {
2019     int i;
2020     struct server *ts;
2021     struct srvAddr *sa;
2022
2023     ObtainWriteLock(&afs_xserver, 721);
2024     ObtainWriteLock(&afs_xsrvAddr, 722);
2025     for (i = 0; i< NSERVERS; i++) {
2026         for (ts = afs_servers[i]; ts; ts = ts->next) {
2027             for (sa = ts->addr; sa; sa = sa->next_sa) {
2028                 afs_MarkServerUpOrDown(sa, 0);
2029             }
2030         }
2031     }
2032     ReleaseWriteLock(&afs_xsrvAddr);
2033     ReleaseWriteLock(&afs_xserver);
2034 }