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