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